diff --git a/build.gradle.kts b/build.gradle.kts index 71908a6..485a85e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -57,8 +57,8 @@ dependencies { implementation(kotlin("stdlib-jdk8")) implementation(kotlin("reflect")) - val vvVer = "4.4.0" - val vbVer = "4.4.0" + val vvVer = "4.4.1" + val vbVer = "4.4.1" val vrVer = "f879184" implementation("com.viaversion:viaversion:$vvVer") { isTransitive = false } implementation("com.viaversion:viabackwards:$vbVer") { isTransitive = false } diff --git a/src/main/java/com/viaversion/aas/codec/packet/play/ServerboundChatCommand.java b/src/main/java/com/viaversion/aas/codec/packet/play/ServerboundChatCommand.java new file mode 100644 index 0000000..ff87f1c --- /dev/null +++ b/src/main/java/com/viaversion/aas/codec/packet/play/ServerboundChatCommand.java @@ -0,0 +1,134 @@ +package com.viaversion.aas.codec.packet.play; + +import com.viaversion.aas.codec.packet.Packet; +import com.viaversion.viaversion.api.minecraft.PlayerMessageSignature; +import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; +import com.viaversion.viaversion.api.type.Type; +import io.netty.buffer.ByteBuf; +import org.jetbrains.annotations.NotNull; + +public class ServerboundChatCommand implements Packet { + private String message; + private long timestamp; + private long salt; + private ArgumentSignature[] signatures; + private boolean signedPreview; + private PlayerMessageSignature[] lastSeenMessages; + private PlayerMessageSignature lastReceivedMessage; + + + public static class ArgumentSignature { + private String argumentName; + private byte[] signature; + + public ArgumentSignature(String argumentName, byte[] signature) { + this.argumentName = argumentName; + this.signature = signature; + } + + public String getArgumentName() { + return argumentName; + } + + public void setArgumentName(String argumentName) { + this.argumentName = argumentName; + } + + public byte[] getSignature() { + return signature; + } + + public void setSignature(byte[] signature) { + this.signature = signature; + } + } + + @Override + public void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception { + message = Type.STRING.read(byteBuf); + timestamp = byteBuf.readLong(); + salt = byteBuf.readLong(); + signatures = new ArgumentSignature[Type.VAR_INT.readPrimitive(byteBuf)]; + for (int i = 0; i < signatures.length; i++) { + signatures[i] = new ArgumentSignature(Type.STRING.read(byteBuf), Type.BYTE_ARRAY_PRIMITIVE.read(byteBuf)); + } + signedPreview = byteBuf.readBoolean(); + if (protocolVersion >= ProtocolVersion.v1_19_1.getVersion()) { + lastSeenMessages = Type.PLAYER_MESSAGE_SIGNATURE_ARRAY.read(byteBuf); + lastReceivedMessage = Type.OPTIONAL_PLAYER_MESSAGE_SIGNATURE.read(byteBuf); + } + } + + @Override + public void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception { + Type.STRING.write(byteBuf, message); + byteBuf.writeLong(timestamp); + byteBuf.writeLong(salt); + Type.VAR_INT.writePrimitive(byteBuf, signatures.length); + for (ArgumentSignature signature : signatures) { + Type.STRING.write(byteBuf, signature.getArgumentName()); + Type.BYTE_ARRAY_PRIMITIVE.write(byteBuf, signature.getSignature()); + } + byteBuf.writeBoolean(signedPreview); + if (protocolVersion >= ProtocolVersion.v1_19_1.getVersion()) { + Type.PLAYER_MESSAGE_SIGNATURE_ARRAY.write(byteBuf, lastSeenMessages); + Type.OPTIONAL_PLAYER_MESSAGE_SIGNATURE.write(byteBuf, lastReceivedMessage); + } + } + + public ArgumentSignature[] getSignatures() { + return signatures; + } + + public void setSignatures(ArgumentSignature[] signatures) { + this.signatures = signatures; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public long getSalt() { + return salt; + } + + public void setSalt(long salt) { + this.salt = salt; + } + + public boolean isSignedPreview() { + return signedPreview; + } + + public void setSignedPreview(boolean signedPreview) { + this.signedPreview = signedPreview; + } + + public PlayerMessageSignature[] getLastSeenMessages() { + return lastSeenMessages; + } + + public void setLastSeenMessages(PlayerMessageSignature[] lastSeenMessages) { + this.lastSeenMessages = lastSeenMessages; + } + + public PlayerMessageSignature getLastReceivedMessage() { + return lastReceivedMessage; + } + + public void setLastReceivedMessage(PlayerMessageSignature lastReceivedMessage) { + this.lastReceivedMessage = lastReceivedMessage; + } +} diff --git a/src/main/java/com/viaversion/aas/codec/packet/play/ServerboundChatMessage.java b/src/main/java/com/viaversion/aas/codec/packet/play/ServerboundChatMessage.java new file mode 100644 index 0000000..4c1e667 --- /dev/null +++ b/src/main/java/com/viaversion/aas/codec/packet/play/ServerboundChatMessage.java @@ -0,0 +1,100 @@ +package com.viaversion.aas.codec.packet.play; + +import com.viaversion.aas.codec.packet.Packet; +import com.viaversion.viaversion.api.minecraft.PlayerMessageSignature; +import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; +import com.viaversion.viaversion.api.type.Type; +import io.netty.buffer.ByteBuf; +import org.jetbrains.annotations.NotNull; + +public class ServerboundChatMessage implements Packet { + private String message; + private long timestamp; + private long salt; + private byte[] signature; + private boolean signedPreview; + private PlayerMessageSignature[] lastSeenMessages; + private PlayerMessageSignature lastReceivedMessage; + + @Override + public void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception { + message = Type.STRING.read(byteBuf); + timestamp = byteBuf.readLong(); + salt = byteBuf.readLong(); + signature = Type.BYTE_ARRAY_PRIMITIVE.read(byteBuf); + signedPreview = byteBuf.readBoolean(); + if (protocolVersion >= ProtocolVersion.v1_19_1.getVersion()) { + lastSeenMessages = Type.PLAYER_MESSAGE_SIGNATURE_ARRAY.read(byteBuf); + lastReceivedMessage = Type.OPTIONAL_PLAYER_MESSAGE_SIGNATURE.read(byteBuf); + } + } + + @Override + public void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception { + Type.STRING.write(byteBuf, message); + byteBuf.writeLong(timestamp); + byteBuf.writeLong(salt); + Type.BYTE_ARRAY_PRIMITIVE.write(byteBuf, signature); + byteBuf.writeBoolean(signedPreview); + if (protocolVersion >= ProtocolVersion.v1_19_1.getVersion()) { + Type.PLAYER_MESSAGE_SIGNATURE_ARRAY.write(byteBuf, lastSeenMessages); + Type.OPTIONAL_PLAYER_MESSAGE_SIGNATURE.write(byteBuf, lastReceivedMessage); + } + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public long getTimestamp() { + return timestamp; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public long getSalt() { + return salt; + } + + public void setSalt(long salt) { + this.salt = salt; + } + + public byte[] getSignature() { + return signature; + } + + public void setSignature(byte[] signature) { + this.signature = signature; + } + + public boolean isSignedPreview() { + return signedPreview; + } + + public void setSignedPreview(boolean signedPreview) { + this.signedPreview = signedPreview; + } + + public PlayerMessageSignature[] getLastSeenMessages() { + return lastSeenMessages; + } + + public void setLastSeenMessages(PlayerMessageSignature[] lastSeenMessages) { + this.lastSeenMessages = lastSeenMessages; + } + + public PlayerMessageSignature getLastReceivedMessage() { + return lastReceivedMessage; + } + + public void setLastReceivedMessage(PlayerMessageSignature lastReceivedMessage) { + this.lastReceivedMessage = lastReceivedMessage; + } +} diff --git a/src/main/kotlin/com/viaversion/aas/codec/packet/PacketRegistry.kt b/src/main/kotlin/com/viaversion/aas/codec/packet/PacketRegistry.kt index f8e21cf..e0118cf 100644 --- a/src/main/kotlin/com/viaversion/aas/codec/packet/PacketRegistry.kt +++ b/src/main/kotlin/com/viaversion/aas/codec/packet/PacketRegistry.kt @@ -7,6 +7,8 @@ import com.viaversion.aas.codec.packet.handshake.Handshake import com.viaversion.aas.codec.packet.login.* import com.viaversion.aas.codec.packet.play.Kick import com.viaversion.aas.codec.packet.play.PluginMessage +import com.viaversion.aas.codec.packet.play.ServerboundChatCommand +import com.viaversion.aas.codec.packet.play.ServerboundChatMessage import com.viaversion.aas.codec.packet.play.SetPlayCompression import com.viaversion.aas.codec.packet.status.StatusPing import com.viaversion.aas.codec.packet.status.StatusPong @@ -25,7 +27,9 @@ import com.viaversion.viaversion.protocols.protocol1_16to1_15_2.ClientboundPacke import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.ClientboundPackets1_17 import com.viaversion.viaversion.protocols.protocol1_18to1_17_1.ClientboundPackets1_18 import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.ClientboundPackets1_19_1 +import com.viaversion.viaversion.protocols.protocol1_19_1to1_19.ServerboundPackets1_19_1 import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.ClientboundPackets1_19 +import com.viaversion.viaversion.protocols.protocol1_19to1_18_2.ServerboundPackets1_19 import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8 import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9 import io.netty.buffer.ByteBuf @@ -36,6 +40,7 @@ import java.util.function.Supplier object PacketRegistry { // state, direction, packet id, protocol version -> entry val entriesDecoding = hashMapOf, RangeMap>() + // direction, type, protocol version -> entry val entriesEncoding = hashMapOf>, RangeMap>() @@ -80,7 +85,8 @@ object PacketRegistry { ProtocolVersion.v1_16_2..ProtocolVersion.v1_16_4 to ClientboundPackets1_16_2.DISCONNECT.id, ProtocolVersion.v1_17..ProtocolVersion.v1_17_1 to ClientboundPackets1_17.DISCONNECT.id, ProtocolVersion.v1_18..ProtocolVersion.v1_18_2 to ClientboundPackets1_18.DISCONNECT.id, - ProtocolVersion.v1_19..ProtocolVersion.v1_19_1 to ClientboundPackets1_19.DISCONNECT.id + ProtocolVersion.v1_19.singleton to ClientboundPackets1_19.DISCONNECT.id, + ProtocolVersion.v1_19_1.singleton to ClientboundPackets1_19_1.DISCONNECT.id ) ) register( @@ -105,6 +111,20 @@ object PacketRegistry { ProtocolVersion.v1_8.singleton, ClientboundPackets1_8.SET_COMPRESSION.id ) + register( + State.PLAY, Direction.SERVERBOUND, ::ServerboundChatCommand, + mapOf( + ProtocolVersion.v1_19.singleton to ServerboundPackets1_19.CHAT_COMMAND.id, + ProtocolVersion.v1_19_1.singleton to ServerboundPackets1_19_1.CHAT_COMMAND.id + ) + ) + register( + State.PLAY, Direction.SERVERBOUND, ::ServerboundChatMessage, + mapOf( + ProtocolVersion.v1_19.singleton to ServerboundPackets1_19.CHAT_MESSAGE.id, + ProtocolVersion.v1_19_1.singleton to ServerboundPackets1_19_1.CHAT_MESSAGE.id + ) + ) } operator fun ProtocolVersion.rangeTo(o: ProtocolVersion): Range { diff --git a/src/main/kotlin/com/viaversion/aas/handler/MinecraftHandler.kt b/src/main/kotlin/com/viaversion/aas/handler/MinecraftHandler.kt index bb15545..14401b2 100644 --- a/src/main/kotlin/com/viaversion/aas/handler/MinecraftHandler.kt +++ b/src/main/kotlin/com/viaversion/aas/handler/MinecraftHandler.kt @@ -14,6 +14,7 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import java.net.SocketAddress import java.nio.channels.ClosedChannelException +import java.util.concurrent.ThreadLocalRandom class MinecraftHandler( val data: ConnectionData, @@ -61,8 +62,9 @@ class MinecraftHandler( if (cause is ProxyConnectException && failedProxy(ctx)) return if (cause is CancelCodecException) return if (cause is ClosedChannelException) return - mcLogger.debug("Exception: ", cause) - disconnect("$cause") + val exceptionId = ThreadLocalRandom.current().nextInt().toUInt().toString(36) + mcLogger.debug("Exception $exceptionId: ", cause) + disconnect("$cause #$exceptionId") } fun disconnect(s: String) { diff --git a/src/main/kotlin/com/viaversion/aas/handler/state/LoginState.kt b/src/main/kotlin/com/viaversion/aas/handler/state/LoginState.kt index 0bbeae0..979ce64 100644 --- a/src/main/kotlin/com/viaversion/aas/handler/state/LoginState.kt +++ b/src/main/kotlin/com/viaversion/aas/handler/state/LoginState.kt @@ -48,7 +48,7 @@ class LoginState : ConnectionState { is LoginStart -> handleLoginStart(handler, packet) is CryptoResponse -> handleCryptoResponse(handler, packet) is PluginResponse -> handlePluginResponse(handler, packet) - is LoginDisconnect -> forward(handler, packet) + is LoginDisconnect -> handleLoginDisconnect(handler, packet) is CryptoRequest -> handleCryptoRequest(handler, packet) is LoginSuccess -> handleLoginSuccess(handler, packet) is SetCompression -> handleCompression(handler, packet) @@ -57,6 +57,11 @@ class LoginState : ConnectionState { } } + private fun handleLoginDisconnect(handler: MinecraftHandler, packet: LoginDisconnect) { + mcLogger.debug("{} disconnected on login: {}", handler.endRemoteAddress.toString(), packet.msg) + forward(handler, packet) + } + private fun handlePluginResponse(handler: MinecraftHandler, packet: PluginResponse) { if (handleReauthResponse(packet)) return forward(handler, packet) diff --git a/src/main/kotlin/com/viaversion/aas/handler/state/PlayState.kt b/src/main/kotlin/com/viaversion/aas/handler/state/PlayState.kt index 7160a0c..4602d94 100644 --- a/src/main/kotlin/com/viaversion/aas/handler/state/PlayState.kt +++ b/src/main/kotlin/com/viaversion/aas/handler/state/PlayState.kt @@ -5,9 +5,12 @@ import com.viaversion.aas.codec.packet.Packet import com.viaversion.aas.codec.packet.UnknownPacket import com.viaversion.aas.codec.packet.play.Kick import com.viaversion.aas.codec.packet.play.PluginMessage +import com.viaversion.aas.codec.packet.play.ServerboundChatCommand +import com.viaversion.aas.codec.packet.play.ServerboundChatMessage import com.viaversion.aas.codec.packet.play.SetPlayCompression import com.viaversion.aas.config.VIAaaSConfig import com.viaversion.aas.handler.* +import com.viaversion.aas.mcLogger import com.viaversion.aas.parseProtocol import com.viaversion.aas.util.StacklessException import com.viaversion.aas.writeFlushClose @@ -26,6 +29,13 @@ object PlayState : ConnectionState { packet is UnknownPacket && (packet.id !in 0..127) -> throw StacklessException("Invalid packet id!") packet is PluginMessage && !handler.frontEnd -> modifyPluginMessage(handler, packet) packet is SetPlayCompression -> return handleCompression(handler, packet) + packet is Kick -> mcLogger.debug( + "{} disconnected on play: {}", + handler.endRemoteAddress.toString(), + packet.msg + ) + packet is ServerboundChatCommand -> modifyChatCommand(packet) + packet is ServerboundChatMessage -> modifyChatMessage(packet) } forward(handler, ReferenceCountUtil.retain(packet)) } @@ -57,6 +67,16 @@ object PlayState : ConnectionState { } } + private fun modifyChatCommand(chatCommand: ServerboundChatCommand) { + // todo handle signatures? + chatCommand.isSignedPreview = false + chatCommand.signatures = emptyArray() + } + + private fun modifyChatMessage(chatMessage: ServerboundChatMessage) { + chatMessage.signature = byteArrayOf() + } + override fun disconnect(handler: MinecraftHandler, msg: String) { super.disconnect(handler, msg) writeFlushClose( diff --git a/src/main/kotlin/com/viaversion/aas/protocol/AspirinProtocols.kt b/src/main/kotlin/com/viaversion/aas/protocol/AspirinProtocols.kt index d81e00d..aa87fa8 100644 --- a/src/main/kotlin/com/viaversion/aas/protocol/AspirinProtocols.kt +++ b/src/main/kotlin/com/viaversion/aas/protocol/AspirinProtocols.kt @@ -10,7 +10,7 @@ import com.viaversion.viaversion.api.protocol.version.ProtocolVersion val sharewareVersion = ProtocolVersion.register(1, "3D Shareware v1.34") fun registerAspirinProtocols() { - Via.getManager().protocolManager.setOnlyCheckLoweringPathEntries(false) // Fixes 1.19.1 -> 1.18.2 -> 1.19 path + Via.getManager().protocolManager.maxPathDeltaIncrease = -1 // shareware id is weird Via.getManager().protocolManager.registerProtocol(Protocol1_8To1_7_6, ProtocolVersion.v1_8, ProtocolVersion.v1_7_6) // todo fix version checks Via.getManager().protocolManager.registerProtocol(ProtocolSharewareto1_14(), sharewareVersion, ProtocolVersion.v1_14)