Files
mcsrv/prePlayPackets.go
2024-10-26 12:41:37 +02:00

527 lines
12 KiB
Go

package main
import (
"bytes"
"encoding/json"
"errors"
"github.com/google/uuid"
"math/rand"
"time"
)
func getHandshakePacket(data *bytes.Buffer) (version int32, address string, port uint16, nextState int32, err error) {
version, err = receiveVarint(data)
address, err = receiveString(data)
port = receiveUint16(data)
nextState, err = receiveVarint(data)
return
}
func encodeTextComponent(buffer *bytes.Buffer, component TextComponent) (err error) {
// First, serialize the component to JSON
jsonData, err := json.Marshal(component)
if err != nil {
return err
}
addString(buffer, string(jsonData))
return
}
func getPingPacket(data *bytes.Buffer) (payload int64, err error) {
payload = receiveInt64(data)
return
}
func getLoginStart(data *bytes.Buffer) (userName string, playerUUID uuid.UUID, err error) {
userName, err = receiveString(data)
playerUUID, err = receiveUUID(data)
return
}
// Decodes encryption response data from the buffer.
func getEncryptionResponse(data *bytes.Buffer) (sharedSecret []byte, verifyToken []byte, err error) {
// Read sharedSecret length using VarInt
sharedSecretLen, err := receiveVarint(data)
if err != nil {
return nil, nil, err
}
// Read sharedSecret bytes
sharedSecret = make([]byte, sharedSecretLen)
_, err = data.Read(sharedSecret)
if err != nil {
return nil, nil, err
}
// Read verifyToken length using VarInt
verifyTokenLen, err := receiveVarint(data)
if err != nil {
return nil, nil, err
}
// Read verifyToken bytes
verifyToken = make([]byte, verifyTokenLen)
_, err = data.Read(verifyToken)
if err != nil {
return nil, nil, err
}
return sharedSecret, verifyToken, nil
}
func getClientInformation(data *bytes.Buffer) (locale string, viewDistance int8, chatMode int32, chatColors bool, skinParts uint8, isRightHanded bool, textFiltering bool, serverListing bool, err error) {
var offset int32
// Decode locale string
locale, err = receiveString(data)
if err != nil {
return
}
// Decode viewDistance
viewDistance = int8(data.Bytes()[offset])
offset++
// Decode chatMode
chatMode, err = receiveVarint(data)
if err != nil {
return
}
// Decode chatColors
chatColors, err = receiveBool(data)
if err != nil {
return
}
// Decode skinParts
skinParts = data.Bytes()[offset]
offset++
// Decode isRightHanded
mainHand, err := receiveVarint(data)
if err != nil {
return
}
isRightHanded = mainHand == 1
// Decode textFiltering
textFiltering, err = receiveBool(data)
if err != nil {
return
}
// Decode serverListing
serverListing, err = receiveBool(data)
if err != nil {
return
}
return
}
func getPluginPacket(inData *bytes.Buffer) (key string, data *bytes.Buffer, err error) {
key, err = receiveString(inData)
data = inData
return
}
func (player *Player) getResourcePackPacket(data *bytes.Buffer) (err error) {
packUUID, err := receiveUUID(data)
if err != nil {
return
}
result, err := receiveVarint(data)
player.resourcePackResponse[packUUID] = result
return
}
func (player *Player) getDataPacksPacket(data *bytes.Buffer) (err error) {
packCount, err := receiveVarint(data)
if err != nil {
return err
}
for i := 0; i < int(packCount); i++ {
namespace, err := receiveString(data)
if err != nil {
return err
}
id, err := receiveString(data)
if err != nil {
return err
}
version, err := receiveString(data)
if err != nil {
return err
}
player.knownPacks = append(player.knownPacks, DatapackInfo{
Namespace: namespace,
ID: id,
Version: version,
})
}
return
}
func (player *Player) sendPongPacket(payload int64) (err error) {
var buf bytes.Buffer
addInt64(&buf, payload)
err = player.sendPacket(0x01, &buf)
if err != nil {
return
}
return
}
func (player *Player) sendDisconnect(reason string) (err error) {
var buf bytes.Buffer
addString(&buf, reason)
switch player.state {
case 2: //login
err = player.sendPacket(0x00, &buf)
case 3: //configuration
err = player.sendPacket(0x02, &buf)
case 4: //play
err = player.sendPacket(0x1D, &buf)
}
return
}
func (player *Player) sendEncryptionRequest() error {
var buf bytes.Buffer
// Send an empty server ID
addVarint(&buf, int32(len(serverID))) // VarInt length of server ID (0)
if len(serverID) > 0 {
buf.Write(serverID)
}
// Continue with the rest of the packet (public key, token, etc.)
serverPubKeyBytes, err := ExportRSAPublicKey(serverPublicKey)
if err != nil {
return err
}
verifyToken, err := generateRandomBytes(4)
if err != nil {
return err
}
player.verifyToken = verifyToken
addVarint(&buf, int32(len(serverPubKeyBytes)))
buf.Write(serverPubKeyBytes)
addVarint(&buf, int32(len(player.verifyToken)))
buf.Write(player.verifyToken)
// Indicate that encryption is enabled
addBool(&buf, true)
// Send the packet with ID 0x01 (encryption request)
err = player.sendPacket(0x01, &buf)
if err != nil {
return err
}
return nil
}
func (player *Player) sendLoginSuccess() error {
var buf bytes.Buffer
addUUID(&buf, player.uuid)
addString(&buf, player.Entity.Name)
addVarint(&buf, int32(len(player.profile.Properties)))
for _, property := range player.profile.Properties {
addString(&buf, property.Name)
addString(&buf, property.Value)
isSigned := len(property.Signature) > 0
addBool(&buf, isSigned)
if isSigned {
addString(&buf, property.Signature)
}
}
addBool(&buf, true)
return player.sendPacket(0x02, &buf)
}
func (player *Player) sendKeepAlive() error {
player.keepAlivePayload = rand.Int63()
player.keepAliveSentTimestamp = time.Now().Unix()
var buf bytes.Buffer
addInt64(&buf, player.keepAlivePayload)
switch player.state {
case 3:
return player.sendPacket(0x04, &buf)
case 4:
return player.sendPacket(0x26, &buf)
}
return errors.New("invalid keep alive state")
}
func (player *Player) sendKeepAlives() {
for {
err := player.sendKeepAlive()
if err != nil {
break
}
time.Sleep(18 * time.Second)
}
}
func (player *Player) sendPingPacket() error {
player.pingID = rand.Uint32()
var buf bytes.Buffer
addUint32(&buf, player.pingID)
player.pingSentTimestamp = time.Now().Unix()
switch player.state {
case 3:
return player.sendPacket(0x05, &buf)
case 4:
return player.sendPacket(0x36, &buf)
}
return errors.New("invalid ping state")
}
func (player *Player) getPongPacket(data *bytes.Buffer) (err error) {
pingID, err := receiveUint32(data)
if pingID == player.pingID {
player.pingReceivedTimestamp = time.Now().Unix()
}
return
}
func (player *Player) sendResetChat() error {
return player.sendPacket(0x06, &bytes.Buffer{})
}
func (player *Player) sendRegistryData() (err error) {
for _, registryData := range world.RegistryDataThings {
var buf bytes.Buffer
addString(&buf, registryData.RegistryID)
addVarint(&buf, int32(len(registryData.Entries)))
for _, entry := range registryData.Entries {
addString(&buf, entry.EntryID)
addBool(&buf, entry.HasNBT)
if entry.HasNBT {
buf.ReadFrom(entry.NBTData)
}
}
err = player.sendPacket(0x07, &buf)
if err != nil {
return
}
}
return nil
}
func (player *Player) removeResourcePack(packUUID uuid.UUID) (err error) {
var buf bytes.Buffer
hasUUID := packUUID != uuid.Nil
addBool(&buf, hasUUID)
if hasUUID {
addUUID(&buf, packUUID)
}
switch player.state {
case 3:
return player.sendPacket(0x08, &buf)
case 4:
return player.sendPacket(0x45, &buf)
}
return player.sendPacket(0x08, &buf)
}
func (player *Player) addResourcePack(packUUID uuid.UUID, url string, hash string, forced bool, message string) (err error) {
var buf bytes.Buffer
addUUID(&buf, packUUID)
addString(&buf, url)
addString(&buf, hash)
addBool(&buf, forced)
hasMessage := len(message) > 0
addBool(&buf, hasMessage)
if hasMessage {
addString(&buf, message)
}
switch player.state {
case 3:
return player.sendPacket(0x09, &buf)
case 4:
return player.sendPacket(0x46, &buf)
}
return errors.New("invalid resource pack state")
}
func (player *Player) sendTransfer(host string, port uint16) (err error) {
var buf bytes.Buffer
addString(&buf, host)
addVarint(&buf, int32(port))
switch player.state {
case 3:
return player.sendPacket(0x0B, &buf)
case 4:
return player.sendPacket(0x73, &buf)
}
return nil
}
func (player *Player) sendFeatureFlags() error {
var buf bytes.Buffer
addVarint(&buf, int32(len(world.FeatureFlags)))
for _, featureFlag := range world.FeatureFlags {
addString(&buf, featureFlag)
}
return player.sendPacket(0x0C, &buf)
}
func (player *Player) sendUpdateTags() error {
var buf bytes.Buffer
addVarint(&buf, int32(len(world.UpdateTags)))
for _, updateTag := range world.UpdateTags {
addString(&buf, updateTag.TagRegistryIdentifier)
addVarint(&buf, int32(len(updateTag.Tags)))
for _, tag := range updateTag.Tags {
addString(&buf, tag.TagName)
addVarint(&buf, int32(len(tag.Entries)))
for _, entry := range tag.Entries {
addVarint(&buf, entry)
}
}
}
switch player.state {
case 3:
return player.sendPacket(0x0D, &buf)
case 4:
return player.sendPacket(0x78, &buf)
}
return errors.New("invalid update tags state")
}
func (player *Player) sendDataPacks() error {
var buf bytes.Buffer
addVarint(&buf, int32(len(world.DataPacks)))
for _, dataPack := range world.DataPacks {
addString(&buf, dataPack.Namespace)
addString(&buf, dataPack.ID)
addString(&buf, dataPack.Version)
}
return player.sendPacket(0x0E, &buf)
}
func (player *Player) sendReportDetails() (err error) {
var buf bytes.Buffer
addVarint(&buf, int32(len(world.ReportDetails)))
for key, value := range world.ReportDetails {
addString(&buf, key)
addString(&buf, value)
}
switch player.state {
case 3:
return player.sendPacket(0x0F, &buf)
case 4:
return player.sendPacket(0x7A, &buf)
}
return errors.New("invalid report details state")
}
func (player *Player) sendServerLinks() error {
var buf bytes.Buffer
addVarint(&buf, int32(len(world.ServerLinks)))
for _, serverLink := range world.ServerLinks {
if len(serverLink.LabelString) > 0 {
addBool(&buf, false)
addString(&buf, serverLink.LabelString)
} else {
addBool(&buf, true)
addVarint(&buf, serverLink.LabelInt)
}
addString(&buf, serverLink.URL)
}
switch player.state {
case 3:
return player.sendPacket(0x10, &buf)
case 4:
return player.sendPacket(0x7B, &buf)
}
return errors.New("invalid server links state")
}
func (player *Player) sendPluginMessage(channel string, data *bytes.Buffer) (err error) {
var buf bytes.Buffer
addString(&buf, channel)
_, err = buf.ReadFrom(data)
if err != nil {
return err
}
switch player.state {
case 3:
return player.sendPacket(0x01, &buf)
case 4:
return player.sendPacket(0x19, &buf)
}
return errors.New("unknown player state")
}
func (player *Player) sendConfigurationFinish() error {
return player.sendPacket(0x03, &bytes.Buffer{})
}
func (player *Player) sendCompression() error {
var buf bytes.Buffer
addVarint(&buf, CompressionThreshold)
return player.sendPacket(0x03, &buf)
}
func (player *Player) sendStatusResponse(description string) (err error) {
if player.state == 1 {
var playerSamples []PlayerSample
for _, player := range world.Players {
if !player.serverListing || player.uuid == uuid.Nil {
continue
}
playerSamples = append(playerSamples, PlayerSample{
Name: player.Entity.Name,
ID: player.uuid.String(),
})
}
status := ServerStatus{
Version: Version{
Name: VERSION,
Protocol: ProtocolVersion,
},
Players: Players{
Max: maxPlayers,
Online: len(world.Players) - 1,
Sample: playerSamples,
},
Description: Description{description},
Favicon: icon,
EnforcesSecureChat: false,
}
jsonData, err := json.Marshal(status)
if err != nil {
return err
}
var outBuffer bytes.Buffer
addString(&outBuffer, string(jsonData))
err = player.sendPacket(0x00, &outBuffer)
if err != nil {
return err
}
}
return nil
}