Major updates/patches, functionality, api
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
81
rcon/players.go
Normal file
81
rcon/players.go
Normal 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
115
rcon/rcon.go
Normal 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
47
rcon/time.go
Normal 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
|
||||
}
|
Reference in New Issue
Block a user