UP Api
This commit is contained in:
167
utils/MdtInfo.go
Normal file
167
utils/MdtInfo.go
Normal file
@@ -0,0 +1,167 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type GamemodeId int
|
||||
|
||||
const (
|
||||
survival GamemodeId = iota
|
||||
sandbox
|
||||
attack
|
||||
pvp
|
||||
editor
|
||||
)
|
||||
|
||||
type Gamemode struct {
|
||||
Name string `json:"name"`
|
||||
Id GamemodeId `json:"id"`
|
||||
}
|
||||
|
||||
type ServerInfo struct {
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Status string `json:"status"`
|
||||
Name string `json:"name"`
|
||||
Maps string `json:"maps"`
|
||||
Players int `json:"players"`
|
||||
Version int `json:"version"`
|
||||
Wave int `json:"wave"`
|
||||
Vertype string `json:"vertype"`
|
||||
Gamemode Gamemode `json:"gamemode"`
|
||||
Description string `json:"description"`
|
||||
Modename string `json:"modename"`
|
||||
Limit int `json:"limit"`
|
||||
Ping int `json:"ping"`
|
||||
}
|
||||
|
||||
type InfoBuffer struct {
|
||||
*bytes.Reader
|
||||
}
|
||||
|
||||
func (g GamemodeId) Name() string {
|
||||
switch g {
|
||||
case survival:
|
||||
return "生存"
|
||||
case sandbox:
|
||||
return "沙盒"
|
||||
case attack:
|
||||
return "进攻"
|
||||
case pvp:
|
||||
return "PVP"
|
||||
case editor:
|
||||
return "编辑"
|
||||
default:
|
||||
return "Error"
|
||||
}
|
||||
}
|
||||
|
||||
func (r *InfoBuffer) New(b []byte) {
|
||||
r.Reader = bytes.NewReader(b)
|
||||
}
|
||||
|
||||
func (r *InfoBuffer) readString() string {
|
||||
l, _ := r.ReadByte()
|
||||
buf := make([]byte, l)
|
||||
r.Read(buf)
|
||||
return string(buf)
|
||||
}
|
||||
|
||||
func (r *InfoBuffer) getInt() int {
|
||||
var t int32
|
||||
binary.Read(r, binary.BigEndian, &t)
|
||||
return int(t)
|
||||
}
|
||||
|
||||
func (r *InfoBuffer) get() byte {
|
||||
b, _ := r.ReadByte()
|
||||
return b
|
||||
}
|
||||
|
||||
func connectServer(host string) (buf InfoBuffer, err error) {
|
||||
socket, err := net.Dial("udp", host)
|
||||
if err != nil {
|
||||
return InfoBuffer{}, err
|
||||
}
|
||||
defer socket.Close()
|
||||
sendData, _ := hex.DecodeString("FE01")
|
||||
_, err = socket.Write(sendData)
|
||||
if err != nil {
|
||||
return InfoBuffer{}, err
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||
defer cancel()
|
||||
workDone := make(chan struct{}, 1)
|
||||
data := make([]byte, 2048)
|
||||
go func() {
|
||||
_, err = socket.Read(data)
|
||||
workDone <- struct{}{}
|
||||
}()
|
||||
select {
|
||||
case <-workDone:
|
||||
buf.New(data)
|
||||
case <-ctx.Done():
|
||||
return InfoBuffer{}, fmt.Errorf("超时:%v", err)
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
func ping(host string) (int64, error) {
|
||||
startTime := time.Now()
|
||||
conn, err := net.DialTimeout("tcp", host, time.Second*2)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
conn.Close()
|
||||
conn.RemoteAddr()
|
||||
elapsedTime := time.Since(startTime).Milliseconds()
|
||||
return elapsedTime, nil
|
||||
}
|
||||
func GetServerInfo(host string) (ServerInfo, error) {
|
||||
var info ServerInfo
|
||||
ip := strings.Split(host, ":")
|
||||
if len(ip) == 1 {
|
||||
info.Host = host
|
||||
info.Port = 6567
|
||||
} else {
|
||||
info.Host = ip[0]
|
||||
port, err := strconv.Atoi(ip[1])
|
||||
if err != nil {
|
||||
return info, err
|
||||
}
|
||||
info.Port = port
|
||||
}
|
||||
add := fmt.Sprintf("%s:%d", info.Host, info.Port)
|
||||
d, err := ping(add)
|
||||
if err != nil {
|
||||
info.Status = "Offline"
|
||||
return info, err
|
||||
}
|
||||
info.Ping = int(d)
|
||||
buf, err := connectServer(add)
|
||||
if err != nil {
|
||||
info.Status = "Offline"
|
||||
return info, err
|
||||
}
|
||||
info.Status = "Online"
|
||||
info.Name = buf.readString()
|
||||
info.Maps = buf.readString()
|
||||
info.Players = buf.getInt()
|
||||
info.Wave = buf.getInt()
|
||||
info.Version = buf.getInt()
|
||||
info.Vertype = buf.readString()
|
||||
info.Gamemode.Id = GamemodeId(buf.get())
|
||||
info.Gamemode.Name = info.Gamemode.Id.Name()
|
||||
info.Limit = buf.getInt()
|
||||
info.Description = buf.readString()
|
||||
info.Modename = buf.readString()
|
||||
return info, nil
|
||||
}
|
Reference in New Issue
Block a user