Test: complete send chat message without signature

This commit is contained in:
2026-09-07 21:40:33 +08:00
parent 8dca918cfd
commit ebb4ff848d
6 files changed
+118 -7

No files matched your search

@@ -13,7 +13,7 @@ import cn.rtast.libmc.packet.MinecraftPacket
import cn.rtast.libmc.primitives.readVarInt
import cn.rtast.libmc.protocol.protocol.game.effect.EntityEffectFlags
import cn.rtast.libmc.protocol.protocol.game.effect.readEntityEffectFlags
import cn.rtast.libmc.protocol.tick.ticks
import cn.rtast.libmc.protocol.util.ticks
import kotlin.time.Duration
public data class ClientboundEntityEffectPacket(
@@ -11,7 +11,7 @@ import cn.rtast.libmc.stream.BytesBuffer
import cn.rtast.libmc.packet.PacketCodec
import cn.rtast.libmc.packet.MinecraftPacket
import cn.rtast.libmc.primitives.readVarInt
import cn.rtast.libmc.protocol.tick.ticks
import cn.rtast.libmc.protocol.util.ticks
import kotlin.time.Duration
public data class ClientboundPlayerEndCombatPacket(val duration: Duration) : MinecraftPacket {
@@ -5,7 +5,7 @@
*/
package cn.rtast.libmc.protocol.tick
package cn.rtast.libmc.protocol.util
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
@@ -0,0 +1,62 @@
/*
* Copyright © 2026 RTAkland
* Author: RTAkland
* Date: 2026/9/7
*/
package test
import cn.rtast.libmc.primitives.FixedBitSet20
import cn.rtast.libmc.primitives.createFixedBitSet20
import cn.rtast.libmc.stream.BytesBuffer
import kotlin.uuid.Uuid
class ClientChatTracker {
private val lastSeenQueue = ArrayDeque<ByteArray>(20)
var pendingMessageCount: Int = 0
private set
fun onReceivePlayerChat(signature: ByteArray?) {
if (signature == null || signature.size != 256) return
if (lastSeenQueue.size >= 20) lastSeenQueue.removeFirst()
lastSeenQueue.addLast(signature)
pendingMessageCount++
}
fun prepareForOutgoingMessage(): ChatStateSnapshot {
val signatures = lastSeenQueue.toList()
val count = pendingMessageCount
pendingMessageCount = 0
return ChatStateSnapshot(signatures, count)
}
}
data class ChatStateSnapshot(val lastSeenSignatures: List<ByteArray>, val messageCount: Int)
fun createAcknowledgedBitSet(lastSeenSignatures: List<ByteArray>): FixedBitSet20 {
val bitSet = createFixedBitSet20()
for (i in lastSeenSignatures.indices) {
if (i >= 20) break
bitSet[i] = true
}
return bitSet
}
object ChatPacketUtils {
fun computeByteArrayHashCode(bytes: ByteArray): Int {
var result = 1
for (element in bytes) result = 31 * result + element.toInt()
return result
}
fun computePacketChecksum(lastSeenSignatures: List<ByteArray>): Byte {
var combinedHash = 1
for (sig in lastSeenSignatures) {
val sigHash = computeByteArrayHashCode(sig)
combinedHash = 31 * combinedHash + sigHash
}
val resultByte = combinedHash.toByte()
return if (resultByte == 0.toByte()) 1.toByte() else resultByte
}
}
@@ -10,8 +10,8 @@ package test
import cn.rtast.libmc.packet.ClientboundUnknownPacket
import cn.rtast.libmc.protocol.client.createMinecraftClient
import cn.rtast.libmc.protocol.crypto.DefaultProtocolContext
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundPlayerInfoUpdatePacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundWaypointPacket
import cn.rtast.libmc.protocol.packet.play.clientbound.ClientboundPlayerChatMessagePacket
import cn.rtast.libmc.protocol.packet.play.serverbound.ServerboundChatMessagePacket
import cn.rtast.libmc.protocol.util.generateOfflineUuid
import kotlinx.coroutines.launch
import org.junit.Test
@@ -21,11 +21,14 @@ import java.security.KeyFactory
import java.security.MessageDigest
import java.security.spec.X509EncodedKeySpec
import javax.crypto.Cipher
import kotlin.random.Random
import kotlin.time.Clock
import kotlin.uuid.Uuid
class TestClientTestInJvm {
val accessToken = File("src/jvmTest/resources/accessToken.txt").readText()
private val chatTracker = ClientChatTracker()
fun encrypt(publicKeyBytes: ByteArray, data: ByteArray): ByteArray {
val keySpec = X509EncodedKeySpec(publicKeyBytes)
@@ -84,8 +87,25 @@ class TestClientTestInJvm {
// if (packet !is ClientboundWaypointPacket)
// println("$direction -> $packet")
// }
// cli.onPacket<ClientboundUnknownPacket> { println(it) }
cli.onPacket<ClientboundPlayerInfoUpdatePacket> { println(it) }
cli.onPacket<ClientboundUnknownPacket> {
println(it)
val snapshot = chatTracker.prepareForOutgoingMessage()
cli.networkChannel.sendPacket(
ServerboundChatMessagePacket(
"114514", Clock.System.now().toEpochMilliseconds(),
Random.nextLong(),
null, snapshot.messageCount, createAcknowledgedBitSet(snapshot.lastSeenSignatures).toByteArray(),
ChatPacketUtils.computePacketChecksum(snapshot.lastSeenSignatures)
)
)
}
cli.onPacket<ClientboundPlayerChatMessagePacket> {
chatTracker.onReceivePlayerChat(it.messageSignature)
}
// cli.onPacket<ClientboundServerDataPacket> { println(it) }
// cli.onPacket<ClientboundServerLinksPacket> { println(it) }
// cli.onPacket<ClientboundCodeOfConductPacket> { println(it) }
// cli.onPacket<ClientboundPlayerInfoUpdatePacket> { println(it) }
cli.launch { cli.connect() }
while (true) {
}