realms support
This commit is contained in:
2
.idea/dictionaries/cjd00.xml
generated
2
.idea/dictionaries/cjd00.xml
generated
@ -1,11 +1,13 @@
|
|||||||
<component name="ProjectDictionaryState">
|
<component name="ProjectDictionaryState">
|
||||||
<dictionary name="cjd00">
|
<dictionary name="cjd00">
|
||||||
<words>
|
<words>
|
||||||
|
<w>astk</w>
|
||||||
<w>cooldown</w>
|
<w>cooldown</w>
|
||||||
<w>craftable</w>
|
<w>craftable</w>
|
||||||
<w>ender</w>
|
<w>ender</w>
|
||||||
<w>minecraft</w>
|
<w>minecraft</w>
|
||||||
<w>mojang</w>
|
<w>mojang</w>
|
||||||
|
<w>motd</w>
|
||||||
<w>rcon</w>
|
<w>rcon</w>
|
||||||
<w>teleport</w>
|
<w>teleport</w>
|
||||||
</words>
|
</words>
|
||||||
|
@ -10,10 +10,11 @@ There's some library in Go support you to create your Minecraft client or server
|
|||||||
- [x] Chat
|
- [x] Chat
|
||||||
- [x] Parse NBT
|
- [x] Parse NBT
|
||||||
- [x] Simple MC robot lib
|
- [x] Simple MC robot lib
|
||||||
- [x] Mojang authenticate
|
- [x] Yggdrasil
|
||||||
- [x] Minecraft network protocol
|
- [x] Minecraft network protocol
|
||||||
- [x] RCON protocol
|
- [x] RCON protocol
|
||||||
- [x] Saves decoding /encoding
|
- [x] Saves decoding /encoding
|
||||||
|
- [ ] Realms Server
|
||||||
|
|
||||||
bot:
|
bot:
|
||||||
- [x] Swing arm
|
- [x] Swing arm
|
||||||
|
13
realms/invite.go
Normal file
13
realms/invite.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package realms
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// Invite invite player to Realm
|
||||||
|
func (r *Realms) Invite(s Server, name, uuid string) error {
|
||||||
|
pl := struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
UUID string `json:"uuid"`
|
||||||
|
}{Name: name, UUID: uuid}
|
||||||
|
|
||||||
|
return r.post(fmt.Sprintf("/invites/%d", s.ID), pl, struct{}{})
|
||||||
|
}
|
36
realms/mco.go
Normal file
36
realms/mco.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package realms
|
||||||
|
|
||||||
|
import "io/ioutil"
|
||||||
|
|
||||||
|
// Available returns whether the user can access the Minecraft Realms service
|
||||||
|
func (r *Realms) Available() (ok bool, err error) {
|
||||||
|
err = r.get("/mco/available", &ok)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compatible returns whether the clients version is up to date with Realms.
|
||||||
|
// if the client is outdated, it returns OUTDATED,
|
||||||
|
// if the client is running a snapshot, it returns OTHER,
|
||||||
|
// else it returns COMPATIBLE.
|
||||||
|
func (r *Realms) Compatible() (string, error) {
|
||||||
|
resp, err := r.c.Get(Domain + "/mco/client/compatible")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
rp, err := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
return string(rp), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TOS is what to join Realms servers you must agree to.
|
||||||
|
// Call this function will set this flag.
|
||||||
|
func (r *Realms) TOS()error{
|
||||||
|
resp,err:=r.c.Post(Domain+"/mco/tos/agreed","application/json",nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
return nil
|
||||||
|
}
|
88
realms/realms.go
Normal file
88
realms/realms.go
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package realms
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/cookiejar"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Realms struct {
|
||||||
|
c http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Error struct {
|
||||||
|
ErrorCode int
|
||||||
|
ErrorMsg string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Error) Error() string {
|
||||||
|
return fmt.Sprintf("[%d] %s", e.ErrorCode, e.ErrorMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Domain is the URL of Realms API server
|
||||||
|
// Panic if it cannot be parse by url.Parse().
|
||||||
|
var Domain = "https://pc.realms.minecraft.net"
|
||||||
|
|
||||||
|
// New create a new Realms c with version, username, accessToken and UUID without dashes.
|
||||||
|
func New(version, user, astk, uuid string) *Realms {
|
||||||
|
r := &Realms{
|
||||||
|
c: http.Client{},
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
r.c.Jar, err = cookiejar.New(nil)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
d, err := url.Parse(Domain)
|
||||||
|
if err != nil {
|
||||||
|
panic("cannot parse realms.Domain as url: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
r.c.Jar.SetCookies(d, []*http.Cookie{
|
||||||
|
{Name: "user", Value: user},
|
||||||
|
{Name: "version", Value: version},
|
||||||
|
{Name: "sid", Value: "token:" + astk + ":" + uuid},
|
||||||
|
})
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Realms) get(endpoint string, resp interface{}) error {
|
||||||
|
rawResp, err := r.c.Get(Domain + endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer rawResp.Body.Close()
|
||||||
|
|
||||||
|
err = json.NewDecoder(rawResp.Body).Decode(resp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Realms) post(endpoint string, payload, resp interface{}) error {
|
||||||
|
data, err := json.Marshal(payload)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rawResp, err := r.c.Post(Domain+endpoint, "application/json", bytes.NewReader(data))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.NewDecoder(rawResp.Body).Decode(resp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
36
realms/realms_test.go
Normal file
36
realms/realms_test.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package realms
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleRealms() {
|
||||||
|
var r *Realms
|
||||||
|
|
||||||
|
r = New(
|
||||||
|
"1.14.4",
|
||||||
|
"Name",
|
||||||
|
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||||
|
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||||
|
)
|
||||||
|
fmt.Println(r.Available())
|
||||||
|
fmt.Println(r.Compatible())
|
||||||
|
|
||||||
|
servers, err := r.Worlds()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range servers {
|
||||||
|
fmt.Println(v.Name, v.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Second * 5)
|
||||||
|
if err := r.TOS(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Second * 5)
|
||||||
|
fmt.Println(r.Address(servers[0]))
|
||||||
|
}
|
139
realms/server.go
Normal file
139
realms/server.go
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package realms
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
ID int
|
||||||
|
RemoteSubscriptionID string
|
||||||
|
Owner string
|
||||||
|
OwnerUUID string
|
||||||
|
Name string
|
||||||
|
MOTD string
|
||||||
|
State string
|
||||||
|
DaysLeft int
|
||||||
|
Expired bool
|
||||||
|
ExpiredTrial bool
|
||||||
|
WorldType string
|
||||||
|
Players []string
|
||||||
|
MaxPlayers int
|
||||||
|
MiniGameName *string
|
||||||
|
MiniGameID *int
|
||||||
|
MinigameImage *string
|
||||||
|
ActiveSlot int
|
||||||
|
//Slots interface{}
|
||||||
|
Member bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Worlds return a list of servers that the user is invited to or owns.
|
||||||
|
func (r *Realms) Worlds() ([]Server, error) {
|
||||||
|
var resp struct {
|
||||||
|
Servers []Server
|
||||||
|
*Error
|
||||||
|
}
|
||||||
|
|
||||||
|
err := r.get("/worlds", &resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.Error != nil {
|
||||||
|
err = resp.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.Servers, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Server returns a single server listing about a server.
|
||||||
|
// you must be the owner of the server.
|
||||||
|
func (r *Realms) Server(ID int) (s Server, err error) {
|
||||||
|
var resp = struct {
|
||||||
|
*Server
|
||||||
|
*Error
|
||||||
|
}{Server: &s}
|
||||||
|
|
||||||
|
err = r.get(fmt.Sprintf("/worlds/%d", ID), &resp)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.Error != nil {
|
||||||
|
err = resp.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Address used to get the IP address for a server.
|
||||||
|
// Call TOS before you call this function.
|
||||||
|
func (r *Realms) Address(s Server) (string, error) {
|
||||||
|
var resp struct {
|
||||||
|
Address string
|
||||||
|
PendingUpdate bool
|
||||||
|
|
||||||
|
ResourcePackUrl *string
|
||||||
|
ResourcePackHash *string
|
||||||
|
|
||||||
|
*Error
|
||||||
|
}
|
||||||
|
|
||||||
|
err := r.get(fmt.Sprintf("/worlds/v1/%d/join/pc", s.ID), &resp)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.Error != nil {
|
||||||
|
err = resp.Error
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.PendingUpdate {
|
||||||
|
return "", errors.New("pending update")
|
||||||
|
}
|
||||||
|
return resp.Address, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backups returns a list of backups for the world.
|
||||||
|
func (r *Realms) Backups(s Server) ([]int, error) {
|
||||||
|
var bs []int
|
||||||
|
err := r.get(fmt.Sprintf("/worlds/%d/backups", s.ID), &bs)
|
||||||
|
|
||||||
|
return bs, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//func (r *Realms) Download() (link, resURL, resHash string) {
|
||||||
|
// var resp struct {
|
||||||
|
// DownloadLink string
|
||||||
|
// ResourcePackURL *string
|
||||||
|
// ResourcePackHash *string
|
||||||
|
// *Error
|
||||||
|
// }
|
||||||
|
// TODO: What's the $WORLD(1-4) means?
|
||||||
|
// err := r.get(fmt.Sprintf("/worlds/$ID/slot/$WORLD(1-4)/download", s.ID), &resp)
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Ops returns a list of operators for this server.
|
||||||
|
// You must own this server to view this.
|
||||||
|
func (r *Realms) Ops(s Server) (ops []string, err error) {
|
||||||
|
err = r.get(fmt.Sprintf("/ops/%d", s.ID), &ops)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// SubscriptionLife returns the current life of a server subscription.
|
||||||
|
func (r *Realms) SubscriptionLife(s Server) (startDate int64, daysLeft int, Type string, err error) {
|
||||||
|
var resp = struct {
|
||||||
|
StartDate *int64
|
||||||
|
DaysLeft *int
|
||||||
|
SubscriptionType *string
|
||||||
|
}{
|
||||||
|
StartDate: &startDate,
|
||||||
|
DaysLeft: &daysLeft,
|
||||||
|
SubscriptionType: &Type,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = r.get(fmt.Sprintf("/subscriptions/%d", s.ID), &resp)
|
||||||
|
return
|
||||||
|
}
|
Reference in New Issue
Block a user