mirror of
https://github.com/WiiLink24/wfc-server.git
synced 2026-03-21 17:44:58 -05:00
121 lines
2.5 KiB
Go
121 lines
2.5 KiB
Go
package common
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type GameSpyCommand struct {
|
|
Command string
|
|
CommandValue string
|
|
OtherValues map[string]string
|
|
}
|
|
|
|
var (
|
|
ErrInvalidGameSpyCommand = errors.New("invalid GameSpy command received")
|
|
ErrNoGameStatsDataLength = errors.New("no data length found in GameStats message")
|
|
)
|
|
|
|
func parseGameSpyMessage(msg string, gameStats bool) ([]GameSpyCommand, error) {
|
|
if !strings.Contains(msg, `\final\`) {
|
|
return nil, ErrInvalidGameSpyCommand
|
|
}
|
|
|
|
var commands []GameSpyCommand
|
|
for len(msg) > 0 && string(msg[0]) == `\` && strings.Contains(msg, `\final\`) {
|
|
foundCommand := false
|
|
g := GameSpyCommand{
|
|
OtherValues: map[string]string{},
|
|
}
|
|
|
|
for len(msg) > 0 && string(msg[0]) == `\` {
|
|
keyEnd := strings.Index(msg[1:], `\`) + 1
|
|
if keyEnd < 2 {
|
|
return nil, ErrInvalidGameSpyCommand
|
|
}
|
|
|
|
key := msg[1:keyEnd]
|
|
value := ""
|
|
msg = msg[keyEnd+1:]
|
|
|
|
if key == "final" {
|
|
// We are done.
|
|
break
|
|
}
|
|
|
|
if gameStats && key == "data" {
|
|
if g.OtherValues["length"] == "" {
|
|
return nil, ErrNoGameStatsDataLength
|
|
}
|
|
|
|
dataLength, err := strconv.Atoi(g.OtherValues["length"])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(msg) < dataLength+1 {
|
|
return nil, ErrInvalidGameSpyCommand
|
|
}
|
|
|
|
value = msg[:dataLength]
|
|
msg = msg[dataLength:]
|
|
if msg[0] == '\\' {
|
|
msg = msg[1:]
|
|
}
|
|
} else if strings.Contains(msg, `\`) {
|
|
if msg[0] != '\\' {
|
|
valueEnd := strings.Index(msg[1:], `\`)
|
|
value = msg[:valueEnd+1]
|
|
msg = msg[valueEnd+1:]
|
|
}
|
|
} else {
|
|
// We have most likely reached the end of the line.
|
|
// However, we do not want to exit out without parsing the final key.
|
|
value = msg
|
|
}
|
|
|
|
if !foundCommand {
|
|
g.Command = key
|
|
g.CommandValue = value
|
|
foundCommand = true
|
|
} else {
|
|
g.OtherValues[key] = value
|
|
}
|
|
}
|
|
|
|
commands = append(commands, g)
|
|
}
|
|
|
|
return commands, nil
|
|
}
|
|
|
|
func ParseGameSpyMessage(msg string) ([]GameSpyCommand, error) {
|
|
return parseGameSpyMessage(msg, false)
|
|
}
|
|
|
|
func ParseGameStatsMessage(msg string) ([]GameSpyCommand, error) {
|
|
return parseGameSpyMessage(msg, true)
|
|
}
|
|
|
|
func CreateGameSpyMessage(command GameSpyCommand) string {
|
|
query := ""
|
|
endQuery := ""
|
|
for k, v := range command.OtherValues {
|
|
if command.Command == "getpdr" && k == "data" {
|
|
endQuery += fmt.Sprintf(`\%s\%s`, k, v)
|
|
} else {
|
|
query += fmt.Sprintf(`\%s\%s`, k, v)
|
|
}
|
|
}
|
|
|
|
query += endQuery
|
|
|
|
if command.Command != "" {
|
|
query = fmt.Sprintf(`\%s\%s%s`, command.Command, command.CommandValue, query)
|
|
}
|
|
|
|
return query + `\final\`
|
|
}
|