Merge #206
This commit is contained in:
@ -1,9 +1,10 @@
|
|||||||
package basic
|
package basic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/google/uuid"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/bot"
|
"github.com/Tnze/go-mc/bot"
|
||||||
"github.com/Tnze/go-mc/chat"
|
"github.com/Tnze/go-mc/chat"
|
||||||
"github.com/Tnze/go-mc/data/packetid"
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package basic
|
package basic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"golang.org/x/exp/slices"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/data/packetid"
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
@ -49,7 +48,7 @@ type Dimension struct {
|
|||||||
} `nbt:"element"`
|
} `nbt:"element"`
|
||||||
}
|
}
|
||||||
type DimensionCodec struct {
|
type DimensionCodec struct {
|
||||||
// What is Below? (wik.vg)
|
// What is Below? (wiki.vg)
|
||||||
ChatType struct {
|
ChatType struct {
|
||||||
Type string `nbt:"type"`
|
Type string `nbt:"type"`
|
||||||
Value []struct {
|
Value []struct {
|
||||||
@ -173,11 +172,10 @@ func (p *Player) handleLoginPacket(packet pk.Packet) error {
|
|||||||
// p.WorldNames[i] = string(v)
|
// p.WorldNames[i] = string(v)
|
||||||
// }
|
// }
|
||||||
p.WorldNames = *(*[]string)(unsafe.Pointer(&WorldNames))
|
p.WorldNames = *(*[]string)(unsafe.Pointer(&WorldNames))
|
||||||
index := slices.IndexFunc(p.DimensionCodec.DimensionType.Value, func(d Dimension) bool {
|
for _, d := range p.DimensionCodec.DimensionType.Value {
|
||||||
return d.Name == string(currentDimension)
|
if d.Name == string(currentDimension) {
|
||||||
})
|
p.Dimension = d
|
||||||
if index != -1 {
|
}
|
||||||
p.Dimension = p.DimensionCodec.DimensionType.Value[index]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = p.c.Conn.WritePacket(pk.Marshal( //PluginMessage packet
|
err = p.c.Conn.WritePacket(pk.Marshal( //PluginMessage packet
|
||||||
@ -221,11 +219,10 @@ func (p *Player) handleRespawnPacket(packet pk.Packet) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return Error{err}
|
return Error{err}
|
||||||
}
|
}
|
||||||
index := slices.IndexFunc(p.DimensionCodec.DimensionType.Value, func(d Dimension) bool {
|
for _, d := range p.DimensionCodec.DimensionType.Value {
|
||||||
return d.Name == string(currentDimension)
|
if d.Name == string(currentDimension) {
|
||||||
})
|
p.Dimension = d
|
||||||
if index != -1 {
|
}
|
||||||
p.Dimension = p.DimensionCodec.DimensionType.Value[index]
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package bot
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/Tnze/go-mc/net"
|
"github.com/Tnze/go-mc/net"
|
||||||
"github.com/Tnze/go-mc/yggdrasil/userApi"
|
"github.com/Tnze/go-mc/yggdrasil/user"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ import (
|
|||||||
type Client struct {
|
type Client struct {
|
||||||
Conn *net.Conn
|
Conn *net.Conn
|
||||||
Auth Auth
|
Auth Auth
|
||||||
KeyPair *userApi.KeyPairResp
|
KeyPair user.KeyPairResp
|
||||||
|
|
||||||
Name string
|
Name string
|
||||||
UUID uuid.UUID
|
UUID uuid.UUID
|
||||||
|
19
bot/login.go
19
bot/login.go
@ -13,14 +13,13 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Tnze/go-mc/yggdrasil/userApi"
|
|
||||||
randN "golang.org/x/exp/rand"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Tnze/go-mc/net/CFB8"
|
"github.com/Tnze/go-mc/net/CFB8"
|
||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
|
"github.com/Tnze/go-mc/yggdrasil/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Auth includes an account
|
// Auth includes an account
|
||||||
@ -47,7 +46,7 @@ func handleEncryptionRequest(c *Client, p pk.Packet) error {
|
|||||||
|
|
||||||
// 响应加密请求
|
// 响应加密请求
|
||||||
// Write Encryption Key Response
|
// Write Encryption Key Response
|
||||||
p, err = genEncryptionKeyResponse(key, er.PublicKey, er.VerifyToken, c.KeyPair)
|
p, err = genEncryptionKeyResponse(key, er.PublicKey, er.VerifyToken, &c.KeyPair)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("gen encryption key response fail: %v", err)
|
return fmt.Errorf("gen encryption key response fail: %v", err)
|
||||||
}
|
}
|
||||||
@ -182,7 +181,7 @@ func newSymmetricEncryption() (key []byte, encoStream, decoStream cipher.Stream)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func genEncryptionKeyResponse(shareSecret, publicKey, verifyToken []byte, keyPair *userApi.KeyPairResp) (erp pk.Packet, err error) {
|
func genEncryptionKeyResponse(shareSecret, publicKey, verifyToken []byte, keyPair *user.KeyPairResp) (erp pk.Packet, err error) {
|
||||||
iPK, err := x509.ParsePKIXPublicKey(publicKey) // Decode Public Key
|
iPK, err := x509.ParsePKIXPublicKey(publicKey) // Decode Public Key
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("decode public key fail: %v", err)
|
err = fmt.Errorf("decode public key fail: %v", err)
|
||||||
@ -202,14 +201,16 @@ func genEncryptionKeyResponse(shareSecret, publicKey, verifyToken []byte, keyPai
|
|||||||
return erp, err
|
return erp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
l := randN.Int63()
|
var l pk.Long
|
||||||
var b bytes.Buffer
|
if _, err := l.ReadFrom(rand.Reader); err != nil {
|
||||||
pk.Long(l).WriteTo(&b)
|
err = fmt.Errorf("generate random number fail: %v", err)
|
||||||
|
return erp, err
|
||||||
|
}
|
||||||
|
|
||||||
key := privateKey.(*rsa.PrivateKey)
|
key := privateKey.(*rsa.PrivateKey)
|
||||||
hash := sha256.New()
|
hash := sha256.New()
|
||||||
hash.Write(verifyToken)
|
hash.Write(verifyToken)
|
||||||
hash.Write(b.Bytes())
|
_, _ = l.WriteTo(hash)
|
||||||
signedData, err := key.Sign(rand.Reader, hash.Sum(nil), crypto.SHA256)
|
signedData, err := key.Sign(rand.Reader, hash.Sum(nil), crypto.SHA256)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("sign verifyToken fail: %v", err)
|
err = fmt.Errorf("sign verifyToken fail: %v", err)
|
||||||
@ -219,7 +220,7 @@ func genEncryptionKeyResponse(shareSecret, publicKey, verifyToken []byte, keyPai
|
|||||||
0x01,
|
0x01,
|
||||||
pk.ByteArray(cryptPK),
|
pk.ByteArray(cryptPK),
|
||||||
pk.Boolean(false),
|
pk.Boolean(false),
|
||||||
pk.Long(l),
|
l,
|
||||||
pk.ByteArray(signedData),
|
pk.ByteArray(signedData),
|
||||||
), nil
|
), nil
|
||||||
} else {
|
} else {
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/Tnze/go-mc/yggdrasil/userApi"
|
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
@ -17,6 +16,7 @@ import (
|
|||||||
"github.com/Tnze/go-mc/data/packetid"
|
"github.com/Tnze/go-mc/data/packetid"
|
||||||
mcnet "github.com/Tnze/go-mc/net"
|
mcnet "github.com/Tnze/go-mc/net"
|
||||||
pk "github.com/Tnze/go-mc/net/packet"
|
pk "github.com/Tnze/go-mc/net/packet"
|
||||||
|
"github.com/Tnze/go-mc/yggdrasil/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProtocolVersion is the protocol version number of minecraft net protocol
|
// ProtocolVersion is the protocol version number of minecraft net protocol
|
||||||
@ -75,7 +75,7 @@ func (c *Client) join(ctx context.Context, d *mcnet.Dialer, addr string) error {
|
|||||||
return LoginErr{"handshake", err}
|
return LoginErr{"handshake", err}
|
||||||
}
|
}
|
||||||
// Login Start
|
// Login Start
|
||||||
pair, err := userApi.GetOrFetchKeyPair(c.Auth.AsTk)
|
pair, err := user.GetOrFetchKeyPair(c.Auth.AsTk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// (No Signature)
|
// (No Signature)
|
||||||
err = c.Conn.WritePacket(pk.Marshal(
|
err = c.Conn.WritePacket(pk.Marshal(
|
||||||
@ -101,7 +101,7 @@ func (c *Client) join(ctx context.Context, d *mcnet.Dialer, addr string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return LoginErr{"login start (with sig)", err}
|
return LoginErr{"login start (with sig)", err}
|
||||||
}
|
}
|
||||||
c.KeyPair = &pair
|
c.KeyPair = pair
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
//Receive Packet
|
//Receive Packet
|
||||||
|
8
data/lang/fur-it/fur_it.go
Normal file
8
data/lang/fur-it/fur_it.go
Normal file
File diff suppressed because one or more lines are too long
8
data/lang/zlm-arab/zlm_arab.go
Normal file
8
data/lang/zlm-arab/zlm_arab.go
Normal file
File diff suppressed because one or more lines are too long
@ -108,11 +108,12 @@ func onSound(id int, category int, x, y, z float64, volume, pitch float32) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func onChatMsg(c *basic.PlayerMessage) error {
|
func onChatMsg(c *basic.PlayerMessage) error {
|
||||||
log.Println("Chat:", c.SignedMessage.String())
|
log.Println("Chat:", c.SignedMessage)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func onSystemMsg(c chat.Message, pos byte) error {
|
func onSystemMsg(c chat.Message, pos byte) error {
|
||||||
log.Printf("System: %v, Location: %v", c.String(), pos)
|
log.Printf("System: %v, Location: %v", c, pos)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,8 +99,9 @@ func onChatMsg(c *basic.PlayerMessage) error {
|
|||||||
log.Println("Chat:", c.SignedMessage.String())
|
log.Println("Chat:", c.SignedMessage.String())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func onSystemMsg(c chat.Message, pos byte) error {
|
func onSystemMsg(c chat.Message, pos byte) error {
|
||||||
log.Printf("System: %v, Location: %v", c.String(), pos)
|
log.Printf("System: %v, Location: %v", c, pos)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,15 +1,36 @@
|
|||||||
package userApi
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ServicesURL = "https://api.minecraftservices.com"
|
var ServicesURL = "https://api.minecraftservices.com"
|
||||||
|
|
||||||
var client = http.DefaultClient
|
var client = http.DefaultClient
|
||||||
|
|
||||||
|
type KeyPairResp struct {
|
||||||
|
KeyPair struct {
|
||||||
|
PrivateKey string `json:"privateKey"`
|
||||||
|
PublicKey string `json:"publicKey"`
|
||||||
|
} `json:"keyPair"`
|
||||||
|
PublicKeySignature string `json:"publicKeySignature"`
|
||||||
|
ExpiresAt time.Time `json:"expiresAt"`
|
||||||
|
RefreshedAfter time.Time `json:"refreshedAfter"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetOrFetchKeyPair(accessToken string) (KeyPairResp, error) {
|
||||||
|
return fetchKeyPair(accessToken) // TODO: cache
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchKeyPair(accessToken string) (KeyPairResp, error) {
|
||||||
|
var keyPairResp KeyPairResp
|
||||||
|
err := post("/player/certificates", accessToken, &keyPairResp)
|
||||||
|
return keyPairResp, err
|
||||||
|
}
|
||||||
|
|
||||||
func post(endpoint string, accessToken string, resp interface{}) error {
|
func post(endpoint string, accessToken string, resp interface{}) error {
|
||||||
rowResp, err := rawPost(endpoint, accessToken)
|
rowResp, err := rawPost(endpoint, accessToken)
|
||||||
if err != nil {
|
if err != nil {
|
@ -1,25 +0,0 @@
|
|||||||
package userApi
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type KeyPairResp struct {
|
|
||||||
KeyPair struct {
|
|
||||||
PrivateKey string `json:"privateKey"`
|
|
||||||
PublicKey string `json:"publicKey"`
|
|
||||||
} `json:"keyPair"`
|
|
||||||
PublicKeySignature string `json:"publicKeySignature"`
|
|
||||||
ExpiresAt time.Time `json:"expiresAt"`
|
|
||||||
RefreshedAfter time.Time `json:"refreshedAfter"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetOrFetchKeyPair(accessToken string) (KeyPairResp, error) {
|
|
||||||
return fetchKeyPair(accessToken) // TODO: cache
|
|
||||||
}
|
|
||||||
|
|
||||||
func fetchKeyPair(accessToken string) (KeyPairResp, error) {
|
|
||||||
var keyPairResp KeyPairResp
|
|
||||||
err := post("/player/certificates", accessToken, &keyPairResp)
|
|
||||||
return keyPairResp, err
|
|
||||||
}
|
|
Reference in New Issue
Block a user