Skip to content

Instantly share code, notes, and snippets.

@PSIget
Created January 25, 2024 13:41
Show Gist options
  • Select an option

  • Save PSIget/ea7f1f581a828ba70d946795540aa9b4 to your computer and use it in GitHub Desktop.

Select an option

Save PSIget/ea7f1f581a828ba70d946795540aa9b4 to your computer and use it in GitHub Desktop.
Получаем информацию о сервере игры STALKER на Golang
package main
import (
"bytes"
"encoding/json"
"fmt"
"net"
"time"
)
type ServerInfo struct {
Info map[string]string `json:"info"`
Players []map[string]string `json:"players"`
Teams []map[string]string `json:"teams"`
}
func main() {
serverIP := "127.0.0.1" // Замените на IP вашего сервера
serverPort := "5449" // Замените на порт вашего сервера
serverInfo, err := getServerInfo(serverIP, serverPort)
if err != nil {
fmt.Println("Ошибка запроса к серверу:", err)
return
}
jsonInfo, err := json.Marshal(serverInfo)
if err != nil {
fmt.Println("Ошибка преобразования в JSON:", err)
return
}
fmt.Println(string(jsonInfo))
}
func getServerInfo(ip, port string) (*ServerInfo, error) {
addr, err := net.ResolveUDPAddr("udp", ip+":"+port)
if err != nil {
return nil, err
}
conn, err := net.DialUDP("udp", nil, addr)
if err != nil {
return nil, err
}
defer conn.Close()
// Отправляем запрос
data := []byte{0xFE, 0xFD, 0x00, 0x04, 0x05, 0x06, 0x07, 0xFF, 0xFF, 0xFF} // Пример запроса
_, err = conn.Write(data)
if err != nil {
return nil, err
}
// Получаем ответ
buffer := make([]byte, 1024)
conn.SetReadDeadline(time.Now().Add(5 * time.Second))
n, _, err := conn.ReadFromUDP(buffer)
if err != nil {
return nil, err
}
// Обрабатываем ответ
response := buffer[:n]
return parseResponse(response)
}
func parseResponse(data []byte) (*ServerInfo, error) {
// Функция парсинга ответа сервера
// Это упрощенный пример, вам возможно понадобится детализировать ее в зависимости от формата ответа сервера
br := bytes.NewReader(data)
info := make(map[string]string)
// Пропускаем первые 5 байтов
br.Seek(5, 0)
// Читаем ключи и значения из ответа
for {
key, err := readString(br)
if err != nil || key == "" {
break
}
value, err := readString(br)
if err != nil {
break
}
info[key] = value
}
// Возвращаем информацию о сервере
return &ServerInfo{Info: info}, nil
}
func readString(reader *bytes.Reader) (string, error) {
var result []byte
for {
b, err := reader.ReadByte()
if err != nil || b == 0 {
break
}
result = append(result, b)
}
return string(result), nil
}
@PSIget
Copy link
Author

PSIget commented Jan 25, 2024

Ответ выглядит так:

{
  "info": {
    "anomalies": "1",
    "anomaliestime": "3",
    "artefactrespawntime": "",
    "artefactscount": "",
    "artefactstaytime": "",
    "autoteambalance": "0",
    "autoteamswap": "1",
    "bearercant_sprint": "",
    "damageblockindicator": "1",
    "damageblocktime": "0",
    "dedicated": "1",
    "forcerespawn": "0",
    "fraglimit": "10",
    "friendlyfire": "100",
    "friendlyindicators": "0",
    "friendlynames": "0",
    "gametype": "teamdeathmatch",
    "gametypename": "4",
    "gamever": "1.5.10",
    "hostname": "new server",
    "hostport": "5450",
    "mapname": "mp_military_1",
    "maprotation": "0",
    "max_ping_limit": "2000",
    "maxplayers": "32",
    "numplayers": "1",
    "numteams": "2",
    "password": "0",
    "reinforcement": "",
    "returnplayers": "",
    "server_up_time": "0d 00:10:11",
    "shieldedbases": "",
    "spectatormodes": "30",
    "timelimit": "0",
    "use_battleye": "1",
    "user_password": "0",
    "voting": "1",
    "warmuptime": "0"
  },
  "players": null,
  "teams": null
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment