Major updates/patches, functionality, api
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Tyler
2020-07-09 21:01:29 -04:00
parent afb79eaceb
commit b52b38179a
32 changed files with 1798 additions and 302 deletions

81
rcon/players.go Normal file
View File

@ -0,0 +1,81 @@
package rcon
import (
"errors"
"fmt"
"regexp"
"strconv"
"strings"
)
var (
userRegexp = regexp.MustCompile("There are (\\d+) of a max of (\\d+) players online: (.*?)$")
teleportedRegexp = regexp.MustCompile("^Teleported (.*?) to (.*?)$")
)
func (r *Session) OnlinePlayers() (int, int, []string, error) {
res, err := r.connection().SendCommand("list")
if err != nil {
return -1, -1, nil, err
}
m := userRegexp.FindStringSubmatch(res)
if m == nil {
return -1, -1, nil, errors.New("unexpected response")
}
online, _ := strconv.Atoi(m[1])
max, _ := strconv.Atoi(m[2])
names := strings.Split(m[3], ", ")
return online, max, names, nil
}
func (r *Session) GetLocation(user string) []float32 {
res, err := r.connection().SendCommand(fmt.Sprintf("execute at %s run tp %s ~ ~ ~", user, user))
if err != nil {
return nil
}
m := teleportedRegexp.FindStringSubmatch(res)
pos, err := SliceToFloats(strings.Split(m[2], ","))
if err != nil {
return nil
}
ret := make([]float32, 3)
for i, v := range pos {
ret[i] = float32(v)
}
return ret
}
func (r *Session) Teleport(user, destination string) (string, error) {
return r.connection().SendCommand(fmt.Sprintf("tp %s %s", user, destination))
}
func SliceToFloats(str []string) ([]float64, error) {
ret := make([]float64, len(str))
var err error
for i, s := range str {
s = strings.TrimSpace(s)
ret[i], err = strconv.ParseFloat(s, 64)
if err != nil {
return nil, err
}
}
return ret, err
}

115
rcon/rcon.go Normal file
View File

@ -0,0 +1,115 @@
package rcon
import (
"encoding/json"
"fmt"
"github.com/tystuyfzand/mcgorcon"
"log"
"time"
)
const (
pingDuration = 30 * time.Second
)
type Session struct {
host string
port int
password string
Debug bool
client *mcgorcon.Client
lastUse time.Time
}
func NewSession(host string, port int, password string) *Session {
return &Session{host: host, port: port, password: password}
}
func (r *Session) Disconnect() {
if r.client != nil {
r.client.Close()
}
}
func (r *Session) connection() *mcgorcon.Client {
if r.client != nil {
if time.Since(r.lastUse) > pingDuration {
_, err := r.client.SendCommand("seed")
if err == nil {
r.lastUse = time.Now()
return r.client
}
} else {
return r.client
}
}
// Open new connection
r.client = r.openConnection()
r.lastUse = time.Now()
return r.client
}
func (r *Session) openConnection() *mcgorcon.Client {
var c *mcgorcon.Client
var err error
for c == nil || err != nil {
c, err = mcgorcon.Dial(r.host, r.port, r.password)
if err == nil {
break
}
<-time.After(10 * time.Second)
}
log.Println("Connection opened")
return c
}
func (r *Session) SendCommand(command string) (string, error) {
if r.Debug {
log.Println("Send command: " + command)
}
return r.connection().SendCommand(command)
}
func (r *Session) ServerMessage(message string) error {
_, err := r.SendCommand(fmt.Sprintf("say %s", message))
return err
}
func (r *Session) SendMessage(user, message string) error {
_, err := r.SendCommand(fmt.Sprintf("msg %s %s", user, message))
return err
}
type colorMessage struct {
Text string `json:"text"`
Color string `json:"color"`
}
func (r *Session) SendColorfulMessage(target, color, message string) error {
messages := []colorMessage{
{Text: message, Color: color},
}
b, err := json.Marshal(messages)
if err != nil {
return err
}
_, err = r.SendCommand(fmt.Sprintf("tellraw %s %s", target, string(b)))
return err
}

47
rcon/time.go Normal file
View File

@ -0,0 +1,47 @@
package rcon
import (
"fmt"
"regexp"
"strconv"
)
var (
timeRegexp = regexp.MustCompile("(\\d+)$")
)
func (r *Session) AddTime(delta int) int {
res, err := r.connection().SendCommand(fmt.Sprintf("time add %d", delta))
if err != nil {
return -1
}
m := timeRegexp.FindStringSubmatch(res)
if m == nil {
return -1
}
ret, _ := strconv.Atoi(m[1])
return ret
}
func (r *Session) GetTime() int {
res, err := r.connection().SendCommand("time query daytime")
if err != nil {
return -1
}
m := timeRegexp.FindStringSubmatch(res)
if m == nil {
return -1
}
v, _ := strconv.Atoi(m[1])
return v
}