Test: complete send chat message without signature
This commit is contained in:
6 files changed
+118
-7
No files matched your search
+1
-1
@@ -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(
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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) {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user