Tnze / go-mc

Collection of Go libraries for Minecraft
https://go-mc.github.io/tutorial/
MIT License
842 stars 114 forks source link

`PlayerMsg` was mistakenly handled as `SystemMsg` #274

Closed snowykami closed 4 months ago

snowykami commented 6 months ago

Describe the bug When client received a player chat message, it was handled as a system message

To Reproduce

  1. Go Version: 1.22.0
  2. GoMC Version: 1.20.1
  3. Code:
package main

import (
    "errors"
    "github.com/Tnze/go-mc/bot"
    "github.com/Tnze/go-mc/bot/basic"
    "github.com/Tnze/go-mc/bot/msg"
    "github.com/Tnze/go-mc/bot/playerlist"
    "github.com/Tnze/go-mc/chat"
    "github.com/maxsupermanhd/go-mc-ms-auth"
    "log"
)

func onSystemMsg(msg chat.Message, overlay bool) error {
    log.Printf("System: %s", msg)
    return nil
}

func onPlayerMsg(msg chat.Message, validated bool) error {
    log.Printf("Player: %s", msg)
    return nil
}

func onDisguisedMsg(msg chat.Message) error {
    log.Printf("Disguised: %v", msg)
    return nil
}

var(
    chatHandler *msg.Manager
    playerList *playerlist.PlayerList
)

func main() {
    mauth, err := GMMAuth.GetMCcredentials("./msauth.json", "88650e7e-efee-4857-b9a9-cf580a00ef43")
    if err != nil {
        log.Print(err)
        return
    }
    log.Print("Authenticated as ", mauth.Name, " (", mauth.UUID, ")")

    client := bot.NewClient()

    client.Auth.UUID = mauth.UUID
    client.Auth.AsTk = mauth.AsTk
    client.Auth.Name = mauth.Name

    playerList = playerlist.New(client)
    player := basic.NewPlayer(client, basic.DefaultSettings, basic.EventsListener{})

    chatHandler = msg.New(client, player, playerList, msg.EventsHandler{})

    err = client.JoinServer("example.com") // My server address
    if err != nil {
        log.Fatal(err)
    }

    log.Println("Login success")
    err = chatHandler.SendMessage("Hello, world!")
    if err != nil {
        return 
    }

    chatHandler = msg.New(client, player, playerList, msg.EventsHandler{
        SystemChat:        onSystemMsg,
        PlayerChatMessage: onPlayerMsg,
        DisguisedChat:     onDisguisedMsg,
    })

    var perr bot.PacketHandlerError
    for {
        if err = client.HandleGame(); err == nil {
            panic("HandleGame never return nil")
        }
        if errors.As(err, &perr) {
            log.Print(perr)
        } else {
            log.Print(err)
        }
    }

}

Expected output I hope player chat message was handled by correct callback function, it didn't cause any errors, but it's too complex to handle situations with FairyChat plugin

2024/03/06 00:11:57 Player: <SF_Kami> Hello

Current output

2024/03/06 00:11:20 Got cached authorization token, trying to authenticate XBL...
2024/03/06 00:11:20 Authorized on XBL, trying to get XSTS token...
2024/03/06 00:11:22 Got XSTS token, trying to get MC token...
2024/03/06 00:11:22 Got MC token, NOT checking that you own the game because it is too complicated and going straight for MC profile...
2024/03/06 00:11:22 Got MC profile
2024/03/06 00:11:22 UUID: xxxxxx
2024/03/06 00:11:22 Name: UserNamexxxxxxxx
2024/03/06 00:11:22 Authenticated as Username (xxxxxxxxxxx)
2024/03/06 00:11:24 Login success
2024/03/06 00:11:24 System: Chat disabled in client options
2024/03/06 00:11:46 System: SF_Kami joined the game
2024/03/06 00:11:57 System: <SF_Kami> Hello

Additional context MCServer version: 1.20.1 Paper online-mode: true

Tnze commented 6 months ago

What if you test it on vanilla server? I guess it's a problem of paper server.

snowykami commented 6 months ago

I had tried vanilla server, it can correctly handle playermsg, but cause another fatal errors. If enforce-secure-profile=true, it will raise some fatal errors.

Tnze commented 6 months ago

Which side is the fatal error on, the go-mc or the server?

snowykami commented 6 months ago

EOF error and message validation failure

  1. If enforce-secure-profile=true in server.properties, when I send message in game, there is an EOF error:
    • Output:
      
      2024/03/08 20:42:22 Got cached authorization token, trying to authenticate XBL...
      2024/03/08 20:42:22 Authorized on XBL, trying to get XSTS token...
      2024/03/08 20:42:24 Got XSTS token, trying to get MC token...
      2024/03/08 20:42:24 Got MC token, NOT checking that you own the game because it is too complicated and going straight for MC profile...
      2024/03/08 20:42:24 Got MC profile
      2024/03/08 20:42:24 UUID: 32815432a47d4c82b4c4f883beca77aa
      2024/03/08 20:42:24 Name: TCP_USER
      2024/03/08 20:42:24 Authenticated as TCP_USER (32815432a47d4c82b4c4f883beca77aa)
      2024/03/08 20:42:25 Login success
      // now, I send a text message in game
      2024/03/08 20:42:29 handle packet ClientboundPlayerChat error: scanning packet field[4] error: unexpected EOF
      panic: runtime error: invalid memory address or nil pointer dereference
      [signal 0xc0000005 code=0x0 addr=0x0 pc=0x10f75f9]

goroutine 1 [running]: github.com/Tnze/go-mc/chat/sign.(Session).verifyHash(0xc00040e068, 0xc0002fc000) C:/Users/snowy/go/pkg/mod/github.com/!tnze/go-mc@v1.20.1/chat/sign/session.go:86 +0x479 github.com/Tnze/go-mc/chat/sign.(Session).VerifyAndUpdate(0xc00040e068, 0xc0002fc000) C:/Users/snowy/go/pkg/mod/github.com/!tnze/go-mc@v1.20.1/chat/sign/session.go:61 +0x2b github.com/Tnze/go-mc/bot/msg.(Manager).handlePlayerChat(0xc000290488, {0x94480?, {0xc000120000?, 0x24f01258880?, 0xc000094470?}}) C:/Users/snowy/go/pkg/mod/github.com/!tnze/go-mc@v1.20.1/bot/msg/chat.go:117 +0x6c5 github.com/Tnze/go-mc/bot.(Client).handlePacket(0xc0000f4120, {0x111f020?, {0xc000120000?, 0xc0000fc2d0?, 0xc000027d68?}}) C:/Users/snowy/go/pkg/mod/github.com/!tnze/go-mc@v1.20.1/bot/ingame.go:87 +0x14c github.com/Tnze/go-mc/bot.(*Client).HandleGame(0xc0000f4120) C:/Users/snowy/go/pkg/mod/github.com/!tnze/go-mc@v1.20.1/bot/ingame.go:28 +0xb1 main.main() D:/snowy/Projects/Go-MC-Onebot/main.go:75 +0x5bf


2. if `enforce-secure-profile=false`, it shows `Chat message validation failure`, I think this is caused by chat message validation that the Mojang add in `1.19.1`.
- Output:

2024/03/08 20:23:05 Got cached authorization token, trying to authenticate XBL... 2024/03/08 20:23:06 Authorized on XBL, trying to get XSTS token... 2024/03/08 20:23:07 Got XSTS token, trying to get MC token... 2024/03/08 20:23:08 Got MC token, NOT checking that you own the game because it is too complicated and going straight for MC profile... 2024/03/08 20:23:08 Got MC profile 2024/03/08 20:23:08 UUID: 32815432a47d4c82b4c4f883beca77aa 2024/03/08 20:23:08 Name: TCP_USER 2024/03/08 20:23:08 Authenticated as TCP_USER (32815432a47d4c82b4c4f883beca77aa) 2024/03/08 20:23:09 Login success 2024/03/08 20:38:39 System: SF_Kami joined the game // now, I send a text message in game 2024/03/08 20:38:46 handle packet ClientboundPlayerChat error: disconnect because: Chat message validation failure


- Test program `main.go`:
```go
package main

import (
    "errors"
    "github.com/Tnze/go-mc/bot"
    "github.com/Tnze/go-mc/bot/basic"
    "github.com/Tnze/go-mc/bot/msg"
    "github.com/Tnze/go-mc/bot/playerlist"
    "github.com/Tnze/go-mc/chat"
    "github.com/maxsupermanhd/go-mc-ms-auth"
    "log"
)

var lastMessageID = uint64(0)

func onSystemMsg(msg chat.Message, overlay bool) error {
    log.Printf("System: %s", msg)
    return nil
}

func onPlayerMsg(msg chat.Message, validated bool) error {
    log.Printf("Player: %s", msg)
    return nil
}

func onDisguisedMsg(msg chat.Message) error {
    log.Printf("Disguised: %v", msg)
    return nil
}

var (
    chatHandler *msg.Manager
    playerList  *playerlist.PlayerList
)

func main() {
    //go connectOneBot()
    mauth, err := GMMAuth.GetMCcredentials("./msauth.json", "88650e7e-efee-4857-b9a9-cf580a00ef43")
    if err != nil {
        log.Print(err)
        return
    }
    log.Print("Authenticated as ", mauth.Name, " (", mauth.UUID, ")")

    client := bot.NewClient()

    client.Auth.UUID = mauth.UUID
    client.Auth.AsTk = mauth.AsTk
    client.Auth.Name = mauth.Name

    playerList = playerlist.New(client)
    player := basic.NewPlayer(client, basic.DefaultSettings, basic.EventsListener{})

    chatHandler = msg.New(client, player, playerList, msg.EventsHandler{})

    err = client.JoinServer("localhost")
    if err != nil {
        log.Fatal(err)
    }

    log.Println("Login success")
    //err = chatHandler.SendMessage("Hello, world!")
    //if err != nil {
    //  return
    //}

    chatHandler = msg.New(client, player, playerList, msg.EventsHandler{
        SystemChat:        onSystemMsg,
        PlayerChatMessage: onPlayerMsg,
        DisguisedChat:     onDisguisedMsg,
    })

    var perr bot.PacketHandlerError
    for {
        if err = client.HandleGame(); err == nil {
            panic("HandleGame never return nil")
        }
        if errors.As(err, &perr) {
            log.Print(perr)
        } else {
            log.Print(err)
        }
    }

}
Tnze commented 6 months ago

Seems like the ClientboundPlayerChat packet format has changed, and go-mc doesn't up to date.

Tnze commented 4 months ago

Fixed in d55614cdb7776036ec7014acd3471c84097f0a51