Merge #206
This commit is contained in:
@ -1,9 +1,10 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/Tnze/go-mc/bot"
|
||||
"github.com/Tnze/go-mc/chat"
|
||||
"github.com/Tnze/go-mc/data/packetid"
|
||||
|
@ -1,7 +1,6 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"golang.org/x/exp/slices"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Tnze/go-mc/data/packetid"
|
||||
@ -49,7 +48,7 @@ type Dimension struct {
|
||||
} `nbt:"element"`
|
||||
}
|
||||
type DimensionCodec struct {
|
||||
// What is Below? (wik.vg)
|
||||
// What is Below? (wiki.vg)
|
||||
ChatType struct {
|
||||
Type string `nbt:"type"`
|
||||
Value []struct {
|
||||
@ -173,11 +172,10 @@ func (p *Player) handleLoginPacket(packet pk.Packet) error {
|
||||
// p.WorldNames[i] = string(v)
|
||||
// }
|
||||
p.WorldNames = *(*[]string)(unsafe.Pointer(&WorldNames))
|
||||
index := slices.IndexFunc(p.DimensionCodec.DimensionType.Value, func(d Dimension) bool {
|
||||
return d.Name == string(currentDimension)
|
||||
})
|
||||
if index != -1 {
|
||||
p.Dimension = p.DimensionCodec.DimensionType.Value[index]
|
||||
for _, d := range p.DimensionCodec.DimensionType.Value {
|
||||
if d.Name == string(currentDimension) {
|
||||
p.Dimension = d
|
||||
}
|
||||
}
|
||||
|
||||
err = p.c.Conn.WritePacket(pk.Marshal( //PluginMessage packet
|
||||
@ -221,11 +219,10 @@ func (p *Player) handleRespawnPacket(packet pk.Packet) error {
|
||||
if err != nil {
|
||||
return Error{err}
|
||||
}
|
||||
index := slices.IndexFunc(p.DimensionCodec.DimensionType.Value, func(d Dimension) bool {
|
||||
return d.Name == string(currentDimension)
|
||||
})
|
||||
if index != -1 {
|
||||
p.Dimension = p.DimensionCodec.DimensionType.Value[index]
|
||||
for _, d := range p.DimensionCodec.DimensionType.Value {
|
||||
if d.Name == string(currentDimension) {
|
||||
p.Dimension = d
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package bot
|
||||
|
||||
import (
|
||||
"github.com/Tnze/go-mc/net"
|
||||
"github.com/Tnze/go-mc/yggdrasil/userApi"
|
||||
"github.com/Tnze/go-mc/yggdrasil/user"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
@ -10,7 +10,7 @@ import (
|
||||
type Client struct {
|
||||
Conn *net.Conn
|
||||
Auth Auth
|
||||
KeyPair *userApi.KeyPairResp
|
||||
KeyPair user.KeyPairResp
|
||||
|
||||
Name string
|
||||
UUID uuid.UUID
|
||||
|
19
bot/login.go
19
bot/login.go
@ -13,14 +13,13 @@ import (
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"github.com/Tnze/go-mc/yggdrasil/userApi"
|
||||
randN "golang.org/x/exp/rand"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/Tnze/go-mc/net/CFB8"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
"github.com/Tnze/go-mc/yggdrasil/user"
|
||||
)
|
||||
|
||||
// Auth includes an account
|
||||
@ -47,7 +46,7 @@ func handleEncryptionRequest(c *Client, p pk.Packet) error {
|
||||
|
||||
// 响应加密请求
|
||||
// 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 {
|
||||
return fmt.Errorf("gen encryption key response fail: %v", err)
|
||||
}
|
||||
@ -182,7 +181,7 @@ func newSymmetricEncryption() (key []byte, encoStream, decoStream cipher.Stream)
|
||||
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
|
||||
if err != nil {
|
||||
err = fmt.Errorf("decode public key fail: %v", err)
|
||||
@ -202,14 +201,16 @@ func genEncryptionKeyResponse(shareSecret, publicKey, verifyToken []byte, keyPai
|
||||
return erp, err
|
||||
}
|
||||
|
||||
l := randN.Int63()
|
||||
var b bytes.Buffer
|
||||
pk.Long(l).WriteTo(&b)
|
||||
var l pk.Long
|
||||
if _, err := l.ReadFrom(rand.Reader); err != nil {
|
||||
err = fmt.Errorf("generate random number fail: %v", err)
|
||||
return erp, err
|
||||
}
|
||||
|
||||
key := privateKey.(*rsa.PrivateKey)
|
||||
hash := sha256.New()
|
||||
hash.Write(verifyToken)
|
||||
hash.Write(b.Bytes())
|
||||
_, _ = l.WriteTo(hash)
|
||||
signedData, err := key.Sign(rand.Reader, hash.Sum(nil), crypto.SHA256)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("sign verifyToken fail: %v", err)
|
||||
@ -219,7 +220,7 @@ func genEncryptionKeyResponse(shareSecret, publicKey, verifyToken []byte, keyPai
|
||||
0x01,
|
||||
pk.ByteArray(cryptPK),
|
||||
pk.Boolean(false),
|
||||
pk.Long(l),
|
||||
l,
|
||||
pk.ByteArray(signedData),
|
||||
), nil
|
||||
} else {
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"github.com/Tnze/go-mc/yggdrasil/userApi"
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
@ -17,6 +16,7 @@ import (
|
||||
"github.com/Tnze/go-mc/data/packetid"
|
||||
mcnet "github.com/Tnze/go-mc/net"
|
||||
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
|
||||
@ -75,7 +75,7 @@ func (c *Client) join(ctx context.Context, d *mcnet.Dialer, addr string) error {
|
||||
return LoginErr{"handshake", err}
|
||||
}
|
||||
// Login Start
|
||||
pair, err := userApi.GetOrFetchKeyPair(c.Auth.AsTk)
|
||||
pair, err := user.GetOrFetchKeyPair(c.Auth.AsTk)
|
||||
if err != nil {
|
||||
// (No Signature)
|
||||
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 {
|
||||
return LoginErr{"login start (with sig)", err}
|
||||
}
|
||||
c.KeyPair = &pair
|
||||
c.KeyPair = pair
|
||||
}
|
||||
for {
|
||||
//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 {
|
||||
log.Println("Chat:", c.SignedMessage.String())
|
||||
log.Println("Chat:", c.SignedMessage)
|
||||
return nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -99,8 +99,9 @@ func onChatMsg(c *basic.PlayerMessage) error {
|
||||
log.Println("Chat:", c.SignedMessage.String())
|
||||
return nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -137,7 +137,7 @@ func TestWriteSectors(t *testing.T) {
|
||||
if len(region.sectors) != expectedSectorsNum {
|
||||
t.Errorf("wrong region sector count. Got: %d, Want: %d", len(region.sectors), expectedSectorsNum)
|
||||
}
|
||||
|
||||
|
||||
if read, err := region.ReadSector(idx, 0); err != nil {
|
||||
t.Fatal("read sector", err)
|
||||
} else if !bytes.Equal(data, read) {
|
||||
|
@ -1,15 +1,36 @@
|
||||
package userApi
|
||||
package user
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
var ServicesURL = "https://api.minecraftservices.com"
|
||||
|
||||
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 {
|
||||
rowResp, err := rawPost(endpoint, accessToken)
|
||||
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