Rename cmd -> examples
This commit is contained in:
115
examples/autofish/autofish.go
Normal file
115
examples/autofish/autofish.go
Normal file
@ -0,0 +1,115 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/Tnze/go-mc/bot/basic"
|
||||
"github.com/Tnze/go-mc/data/packetid"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/Tnze/go-mc/bot"
|
||||
"github.com/Tnze/go-mc/chat"
|
||||
_ "github.com/Tnze/go-mc/data/lang/en-us"
|
||||
"github.com/mattn/go-colorable"
|
||||
)
|
||||
|
||||
const timeout = 45
|
||||
|
||||
var (
|
||||
c *bot.Client
|
||||
p *basic.Player
|
||||
|
||||
watch chan time.Time
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.SetOutput(colorable.NewColorableStdout())
|
||||
c = bot.NewClient()
|
||||
p = basic.NewPlayer(c, basic.DefaultSettings)
|
||||
|
||||
//Register event handlers
|
||||
basic.EventsListener{
|
||||
GameStart: onGameStart,
|
||||
ChatMsg: onChatMsg,
|
||||
Disconnect: onDisconnect,
|
||||
Death: onDeath,
|
||||
}.Attach(c)
|
||||
c.Events.AddListener(bot.PacketHandler{
|
||||
ID: packetid.NamedSoundEffect,
|
||||
Priority: 0,
|
||||
F: func(p pk.Packet) error {
|
||||
return onSound()
|
||||
},
|
||||
})
|
||||
|
||||
//Login
|
||||
err := c.JoinServer("127.0.0.1")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Println("Login success")
|
||||
|
||||
//JoinGame
|
||||
err = c.HandleGame()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func onDeath() error {
|
||||
log.Println("Died and Respawned")
|
||||
// If we exclude Respawn(...) then the player won't press the "Respawn" button upon death
|
||||
return p.Respawn()
|
||||
}
|
||||
|
||||
func onGameStart() error {
|
||||
log.Println("Game start")
|
||||
|
||||
watch = make(chan time.Time)
|
||||
go watchDog()
|
||||
|
||||
return c.UseItem(0)
|
||||
}
|
||||
|
||||
//goland:noinspection SpellCheckingInspection
|
||||
func onSound(name string, category int, x, y, z float64, volume, pitch float32) error {
|
||||
if name == "entity.fishing_bobber.splash" {
|
||||
if err := c.UseItem(0); err != nil { //retrieve
|
||||
return err
|
||||
}
|
||||
log.Println("gra~")
|
||||
time.Sleep(time.Millisecond * 300)
|
||||
if err := c.UseItem(0); err != nil { //throw
|
||||
return err
|
||||
}
|
||||
watch <- time.Now()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func onChatMsg(c chat.Message, pos byte, uuid uuid.UUID) error {
|
||||
log.Println("Chat:", c)
|
||||
return nil
|
||||
}
|
||||
|
||||
func onDisconnect(c chat.Message) error {
|
||||
log.Println("Disconnect:", c)
|
||||
return nil
|
||||
}
|
||||
|
||||
func watchDog() {
|
||||
to := time.NewTimer(time.Second * timeout)
|
||||
for {
|
||||
select {
|
||||
case <-watch:
|
||||
case <-to.C:
|
||||
log.Println("rethrow")
|
||||
if err := c.UseItem(0); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
to.Reset(time.Second * timeout)
|
||||
}
|
||||
}
|
98
examples/daze/daze.go
Normal file
98
examples/daze/daze.go
Normal file
@ -0,0 +1,98 @@
|
||||
// Daze could join an offline-mode server as client.
|
||||
// Just standing there and do nothing. Automatically reborn after five seconds of death.
|
||||
//
|
||||
// BUG(Tnze): Kick by Disconnect: Time Out
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/Tnze/go-mc/bot"
|
||||
"github.com/Tnze/go-mc/bot/basic"
|
||||
"github.com/Tnze/go-mc/chat"
|
||||
_ "github.com/Tnze/go-mc/data/lang/zh-cn"
|
||||
)
|
||||
|
||||
var address = flag.String("address", "127.0.0.1", "The server address")
|
||||
var client *bot.Client
|
||||
var player *basic.Player
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
client = bot.NewClient()
|
||||
client.Auth.Name = "Daze"
|
||||
player = basic.NewPlayer(client, basic.DefaultSettings)
|
||||
basic.EventsListener{
|
||||
GameStart: onGameStart,
|
||||
ChatMsg: onChatMsg,
|
||||
Disconnect: onDisconnect,
|
||||
Death: onDeath,
|
||||
}.Attach(client)
|
||||
|
||||
//Login
|
||||
err := client.JoinServer(*address)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Println("Login success")
|
||||
|
||||
//JoinGame
|
||||
for {
|
||||
if err = client.HandleGame(); err == nil {
|
||||
panic("HandleGame never return nil")
|
||||
}
|
||||
|
||||
if err2 := new(bot.PacketHandlerError); errors.As(err, err2) {
|
||||
if err := new(DisconnectErr); errors.As(err2, err) {
|
||||
log.Print("Disconnect: ", err.Reason)
|
||||
return
|
||||
} else {
|
||||
// print and ignore the error
|
||||
log.Print(err2)
|
||||
}
|
||||
} else {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func onDeath() error {
|
||||
log.Println("Died and Respawned")
|
||||
// If we exclude Respawn(...) then the player won't press the "Respawn" button upon death
|
||||
go func() {
|
||||
time.Sleep(time.Second * 5)
|
||||
err := player.Respawn()
|
||||
if err != nil {
|
||||
log.Print(err)
|
||||
}
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func onGameStart() error {
|
||||
log.Println("Game start")
|
||||
return nil //if err isn't nil, HandleGame() will return it.
|
||||
}
|
||||
|
||||
func onChatMsg(c chat.Message, _ byte, _ uuid.UUID) error {
|
||||
log.Println("Chat:", c.ClearString()) // output chat message without any format code (like color or bold)
|
||||
return nil
|
||||
}
|
||||
|
||||
type DisconnectErr struct {
|
||||
Reason chat.Message
|
||||
}
|
||||
|
||||
func (d DisconnectErr) Error() string {
|
||||
return "disconnect: " + d.Reason.String()
|
||||
}
|
||||
|
||||
func onDisconnect(reason chat.Message) error {
|
||||
// return a error value so that we can stop main loop
|
||||
return DisconnectErr{Reason: reason}
|
||||
}
|
26
examples/luncher/luncher.go
Normal file
26
examples/luncher/luncher.go
Normal file
@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/Tnze/go-mc/yggdrasil"
|
||||
)
|
||||
|
||||
var user = flag.String("user", "", "Can be an email address or player name for unmigrated accounts")
|
||||
var pswd = flag.String("password", "", "Your password")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
resp, err := yggdrasil.Authenticate(*user, *pswd)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
id, name := resp.SelectedProfile()
|
||||
fmt.Println("user:", name)
|
||||
fmt.Println("uuid:", id)
|
||||
fmt.Println("astk:", resp.AccessToken())
|
||||
}
|
125
examples/mcadump/mcadump.go
Normal file
125
examples/mcadump/mcadump.go
Normal file
@ -0,0 +1,125 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"compress/zlib"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/Tnze/go-mc/save/region"
|
||||
)
|
||||
|
||||
var decomp = flag.Bool("x", false, "decompress each chunk to NBT format")
|
||||
var repack = flag.Bool("p", false, "repack .mcc file to .mca")
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
args := flag.Args()
|
||||
|
||||
var o string
|
||||
o = "." // output dir
|
||||
if len(args) < 2 {
|
||||
usage()
|
||||
}
|
||||
for _, f := range args[1:] {
|
||||
fs, err := filepath.Glob(f)
|
||||
checkerr(err)
|
||||
|
||||
if *repack {
|
||||
for _, f := range fs {
|
||||
pack(f, o)
|
||||
}
|
||||
} else {
|
||||
for _, f := range fs {
|
||||
unpack(f, o)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func usage() {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "usage: %s [-x] [-r] r.<X>.<Z>.mc{a,c}\n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// we use this function to check for laziness. Don't scold me >_<
|
||||
func checkerr(err error) {
|
||||
if err != nil {
|
||||
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func unpack(f, o string) {
|
||||
var x, z int
|
||||
rn := filepath.Base(f)
|
||||
_, err := fmt.Sscanf(rn, "r.%d.%d.mca", &x, &z)
|
||||
if err != nil {
|
||||
checkerr(fmt.Errorf("cannot use %s as mca file name: %v", rn, err))
|
||||
}
|
||||
|
||||
r, err := region.Open(f)
|
||||
checkerr(err)
|
||||
defer r.Close()
|
||||
|
||||
for i := 0; i < 32; i++ {
|
||||
for j := 0; j < 32; j++ {
|
||||
if !r.ExistSector(i, j) {
|
||||
continue
|
||||
}
|
||||
|
||||
data, err := r.ReadSector(i, j)
|
||||
checkerr(err)
|
||||
var r io.Reader = bytes.NewReader(data[1:])
|
||||
|
||||
fn := fmt.Sprintf("c.%d.%d.mcc", x*32+i, z*32+j)
|
||||
if *decomp {
|
||||
fn += ".nbt" //解压后就是一个标准的NBT文件,可以加个.nbt后缀
|
||||
switch data[0] {
|
||||
default:
|
||||
err = fmt.Errorf("unknown compression type 0x%02x", data[0])
|
||||
case 1:
|
||||
r, err = gzip.NewReader(r)
|
||||
case 2:
|
||||
r, err = zlib.NewReader(r)
|
||||
}
|
||||
checkerr(err)
|
||||
}
|
||||
|
||||
cf, err := os.OpenFile(filepath.Join(o, fn), os.O_CREATE|os.O_RDWR|os.O_EXCL, 0666)
|
||||
checkerr(err)
|
||||
|
||||
_, err = io.Copy(cf, r)
|
||||
checkerr(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pack(f, o string) {
|
||||
var x, z int
|
||||
rn := filepath.Base(f)
|
||||
_, err := fmt.Sscanf(rn, "c.%d.%d.mcc", &x, &z)
|
||||
if err != nil {
|
||||
checkerr(fmt.Errorf("cannot use %s as mcc file name: %v", rn, err))
|
||||
}
|
||||
|
||||
fn := fmt.Sprintf("r.%d.%d.mca", x>>5, z>>5)
|
||||
r, err := region.Open(fn)
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
r, err = region.Create(filepath.Join(o, fn))
|
||||
}
|
||||
checkerr(err)
|
||||
defer r.Close()
|
||||
|
||||
mcc, err := os.ReadFile(f)
|
||||
checkerr(err)
|
||||
|
||||
rx, rz := region.In(x, z)
|
||||
err = r.WriteSector(rx, rz, mcc)
|
||||
checkerr(err)
|
||||
}
|
17
examples/mcping/README.md
Normal file
17
examples/mcping/README.md
Normal file
@ -0,0 +1,17 @@
|
||||
# mcping
|
||||
|
||||
Ping tool for Minecraft: Java Edition.
|
||||
Just for example. Not recommended for daily use. Use [github.com/go-mc/mcping](github.com/go-mc/mcping) instead, which including SRV parse.
|
||||
|
||||
适用于Minecraft: Java Edition的ping工具。
|
||||
只起示例作用,日常使用建议使用完整版[github.com/go-mc/mcping](github.com/go-mc/mcping),包含SRV解析等功能。
|
||||
|
||||
Install with go tools:
|
||||
```go get -u github.com/Tnze/go-mc/cmd/mcping```
|
||||
`$GOPATH/bin` should in your `$PATH`.
|
||||
|
||||
Install with Homebrew:
|
||||
```brew tap Tnze/tap && brew install mcping```
|
||||
|
||||
Useage:
|
||||
```mcping <hostname>[:port]```
|
72
examples/mcping/mcping.go
Normal file
72
examples/mcping/mcping.go
Normal file
@ -0,0 +1,72 @@
|
||||
// Usage: go run examples/ping/ping.go localhost
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/Tnze/go-mc/bot"
|
||||
"github.com/Tnze/go-mc/chat"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type status struct {
|
||||
Description chat.Message
|
||||
Players struct {
|
||||
Max int
|
||||
Online int
|
||||
Sample []struct {
|
||||
ID uuid.UUID
|
||||
Name string
|
||||
}
|
||||
}
|
||||
Version struct {
|
||||
Name string
|
||||
Protocol int
|
||||
}
|
||||
//favicon ignored
|
||||
}
|
||||
|
||||
func main() {
|
||||
addr := getAddr()
|
||||
fmt.Printf("MCPING (%s):\n", addr)
|
||||
resp, delay, err := bot.PingAndList(addr)
|
||||
if err != nil {
|
||||
fmt.Printf("ping and list server fail: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var s status
|
||||
err = json.Unmarshal(resp, &s)
|
||||
if err != nil {
|
||||
fmt.Print("unmarshal resp fail:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Print(s)
|
||||
fmt.Println("Delay:", delay)
|
||||
}
|
||||
|
||||
func getAddr() string {
|
||||
const usage = "Usage: mcping <hostname>[:port]"
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Println("no host name.", usage)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return os.Args[1]
|
||||
}
|
||||
|
||||
func (s status) String() string {
|
||||
var sb strings.Builder
|
||||
fmt.Fprintln(&sb, "Server:", s.Version.Name)
|
||||
fmt.Fprintln(&sb, "Protocol:", s.Version.Protocol)
|
||||
fmt.Fprintln(&sb, "Description:", s.Description)
|
||||
fmt.Fprintf(&sb, "Players: %d/%d\n", s.Players.Online, s.Players.Max)
|
||||
for _, v := range s.Players.Sample {
|
||||
fmt.Fprintf(&sb, "- [%s] %v\n", v.Name, v.ID)
|
||||
}
|
||||
return sb.String()
|
||||
}
|
164
examples/simpleServer/main.go
Normal file
164
examples/simpleServer/main.go
Normal file
@ -0,0 +1,164 @@
|
||||
// Example minecraft 1.15.2 server
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/Tnze/go-mc/net"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
"github.com/Tnze/go-mc/offline"
|
||||
"github.com/google/uuid"
|
||||
"log"
|
||||
)
|
||||
|
||||
const ProtocolVersion = 578
|
||||
const MaxPlayer = 200
|
||||
|
||||
// Packet IDs
|
||||
const (
|
||||
PlayerPositionAndLookClientbound = 0x36
|
||||
JoinGame = 0x26
|
||||
)
|
||||
|
||||
func main() {
|
||||
l, err := net.ListenMC(":25565")
|
||||
if err != nil {
|
||||
log.Fatalf("Listen error: %v", err)
|
||||
}
|
||||
|
||||
for {
|
||||
conn, err := l.Accept()
|
||||
if err != nil {
|
||||
log.Fatalf("Accept error: %v", err)
|
||||
}
|
||||
go acceptConn(conn)
|
||||
}
|
||||
}
|
||||
|
||||
func acceptConn(conn net.Conn) {
|
||||
defer conn.Close()
|
||||
// handshake
|
||||
protocol, intention, err := handshake(conn)
|
||||
if err != nil {
|
||||
log.Printf("Handshake error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
switch intention {
|
||||
default: //unknown error
|
||||
log.Printf("Unknown handshake intention: %v", intention)
|
||||
case 1: //for status
|
||||
acceptListPing(conn)
|
||||
case 2: //for login
|
||||
handlePlaying(conn, protocol)
|
||||
}
|
||||
}
|
||||
|
||||
func handlePlaying(conn net.Conn, protocol int32) {
|
||||
// login, get player info
|
||||
info, err := acceptLogin(conn)
|
||||
if err != nil {
|
||||
log.Print("Login failed")
|
||||
return
|
||||
}
|
||||
|
||||
// Write LoginSuccess packet
|
||||
|
||||
if err = loginSuccess(conn, info.Name, info.UUID); err != nil {
|
||||
log.Print("Login failed on success")
|
||||
return
|
||||
}
|
||||
|
||||
if err := joinGame(conn); err != nil {
|
||||
log.Print("Login failed on joinGame")
|
||||
return
|
||||
}
|
||||
if err := conn.WritePacket(pk.Marshal(PlayerPositionAndLookClientbound,
|
||||
// https://wiki.vg/index.php?title=Protocol&oldid=16067#Player_Position_And_Look_.28clientbound.29
|
||||
pk.Double(0), pk.Double(0), pk.Double(0), // XYZ
|
||||
pk.Float(0), pk.Float(0), // Yaw Pitch
|
||||
pk.Byte(0), // flag
|
||||
pk.VarInt(0), // TP ID
|
||||
)); err != nil {
|
||||
log.Print("Login failed on sending PlayerPositionAndLookClientbound")
|
||||
return
|
||||
}
|
||||
// Just for block this goroutine. Keep the connection
|
||||
for {
|
||||
var p pk.Packet
|
||||
if err := conn.ReadPacket(&p); err != nil {
|
||||
log.Printf("ReadPacket error: %v", err)
|
||||
break
|
||||
}
|
||||
// KeepAlive packet is not handled, so client might
|
||||
// exit because of "time out".
|
||||
}
|
||||
}
|
||||
|
||||
type PlayerInfo struct {
|
||||
Name string
|
||||
UUID uuid.UUID
|
||||
OPLevel int
|
||||
}
|
||||
|
||||
// acceptLogin check player's account
|
||||
func acceptLogin(conn net.Conn) (info PlayerInfo, err error) {
|
||||
//login start
|
||||
var p pk.Packet
|
||||
err = conn.ReadPacket(&p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = p.Scan((*pk.String)(&info.Name)) //decode username as pk.String
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
//auth
|
||||
const OnlineMode = false
|
||||
if OnlineMode {
|
||||
log.Panic("Not Implement")
|
||||
} else {
|
||||
// offline-mode UUID
|
||||
info.UUID = offline.NameToUUID(info.Name)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// handshake receive and parse Handshake packet
|
||||
func handshake(conn net.Conn) (protocol, intention int32, err error) {
|
||||
var (
|
||||
p pk.Packet
|
||||
Protocol, Intention pk.VarInt
|
||||
ServerAddress pk.String // ignored
|
||||
ServerPort pk.UnsignedShort // ignored
|
||||
)
|
||||
// receive handshake packet
|
||||
if err = conn.ReadPacket(&p); err != nil {
|
||||
return
|
||||
}
|
||||
err = p.Scan(&Protocol, &ServerAddress, &ServerPort, &Intention)
|
||||
return int32(Protocol), int32(Intention), err
|
||||
}
|
||||
|
||||
// loginSuccess send LoginSuccess packet to client
|
||||
func loginSuccess(conn net.Conn, name string, uuid uuid.UUID) error {
|
||||
return conn.WritePacket(pk.Marshal(0x02,
|
||||
pk.String(uuid.String()), //uuid as string with hyphens
|
||||
pk.String(name),
|
||||
))
|
||||
}
|
||||
|
||||
func joinGame(conn net.Conn) error {
|
||||
return conn.WritePacket(pk.Marshal(JoinGame,
|
||||
pk.Int(0), // EntityID
|
||||
pk.UnsignedByte(1), // Gamemode
|
||||
pk.Int(0), // Dimension
|
||||
pk.Long(0), // HashedSeed
|
||||
pk.UnsignedByte(MaxPlayer), // MaxPlayer
|
||||
pk.String("default"), // LevelType
|
||||
pk.VarInt(15), // View Distance
|
||||
pk.Boolean(false), // Reduced Debug Info
|
||||
pk.Boolean(true), // Enable respawn screen
|
||||
))
|
||||
}
|
65
examples/simpleServer/status.go
Normal file
65
examples/simpleServer/status.go
Normal file
@ -0,0 +1,65 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/Tnze/go-mc/chat"
|
||||
"github.com/Tnze/go-mc/net"
|
||||
pk "github.com/Tnze/go-mc/net/packet"
|
||||
"github.com/google/uuid"
|
||||
"log"
|
||||
)
|
||||
|
||||
func acceptListPing(conn net.Conn) {
|
||||
var p pk.Packet
|
||||
for i := 0; i < 2; i++ { // ping or list. Only accept twice
|
||||
err := conn.ReadPacket(&p)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
switch p.ID {
|
||||
case 0x00: //List
|
||||
err = conn.WritePacket(pk.Marshal(0x00, pk.String(listResp())))
|
||||
case 0x01: //Ping
|
||||
err = conn.WritePacket(p)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type player struct {
|
||||
Name string `json:"name"`
|
||||
ID uuid.UUID `json:"id"`
|
||||
}
|
||||
|
||||
// listResp return server status as JSON string
|
||||
func listResp() string {
|
||||
var list struct {
|
||||
Version struct {
|
||||
Name string `json:"name"`
|
||||
Protocol int `json:"protocol"`
|
||||
} `json:"version"`
|
||||
Players struct {
|
||||
Max int `json:"max"`
|
||||
Online int `json:"online"`
|
||||
Sample []player `json:"sample"`
|
||||
} `json:"players"`
|
||||
Description chat.Message `json:"description"`
|
||||
FavIcon string `json:"favicon,omitempty"`
|
||||
}
|
||||
|
||||
list.Version.Name = "Chat Server"
|
||||
list.Version.Protocol = ProtocolVersion
|
||||
list.Players.Max = MaxPlayer
|
||||
list.Players.Online = 123
|
||||
list.Players.Sample = []player{} // must init. can't be nil
|
||||
list.Description = chat.Message{Text: "Powered by go-mc", Color: "blue"}
|
||||
|
||||
data, err := json.Marshal(list)
|
||||
if err != nil {
|
||||
log.Panic("Marshal JSON for status checking fail")
|
||||
}
|
||||
return string(data)
|
||||
}
|
Reference in New Issue
Block a user