A modification-free API for Minecraft utilizing log parsing
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

163 lines
3.2 KiB

package main
import (
"flag"
log "github.com/sirupsen/logrus"
"meow.tf/residentsleeper/commands"
"meow.tf/residentsleeper/events"
"meow.tf/residentsleeper/rcon"
"meow.tf/residentsleeper/scripting/config"
"meow.tf/residentsleeper/scripting/minecraft"
"os"
"path"
"regexp"
"strconv"
"strings"
)
var (
serverPath string
scriptPath string
rconPort int
rconPassword string
debug bool
client *rcon.Session
configRegexp = regexp.MustCompile("^(.*?)=(.*)$")
flagDebug = flag.Bool("debug", false, "debug messages")
)
func init() {
flag.StringVar(&serverPath, "dir", "", "server directory")
flag.StringVar(&scriptPath, "scriptPath", "", "script path override")
}
func main() {
flag.Parse()
debug = *flagDebug
if debug {
log.SetLevel(log.DebugLevel)
}
// Load properties
configPath := path.Join(serverPath, "server.properties")
cfg, err := loadServerConfig(configPath)
if err != nil {
log.WithError(err).Fatalln("Unable to load config")
}
if rconEnabled, ok := cfg["enable-rcon"]; !ok || rconEnabled != "true" {
log.Fatalln("RCON not enabled.")
}
var rconPortStr string
var ok bool
if rconPortStr, ok = cfg["rcon.port"]; !ok {
log.Fatalln("RCON is not enabled: No port set")
}
rconPort, _ = strconv.Atoi(rconPortStr)
if rconPassword, ok = cfg["rcon.password"]; !ok {
log.Fatalln("RCON is not enabled: No password set")
}
events.On(events.Message, handleCommands)
rconHost := "localhost"
if envHost := os.Getenv("RCON_HOST"); envHost != "" {
rconHost = envHost
}
client = rcon.NewSession(rconHost, rconPort, rconPassword)
client.Debug = debug
if scriptPath == "" {
scriptPath = path.Join(serverPath, "scripts")
}
if _, err := os.Stat(scriptPath); !os.IsNotExist(err) {
config.BasePath = path.Join(scriptPath, "config")
minecraft.BasePath = serverPath
minecraft.WorldPath = path.Join(serverPath, cfg["level-name"])
if _, err = os.Stat(config.BasePath); os.IsNotExist(err) {
os.Mkdir(config.BasePath, 0755)
}
log.WithField("path", scriptPath).Info("Loading scripts")
err = loadScripts(scriptPath)
if err != nil {
log.WithError(err).Warn("Unable to load scripts")
}
}
logPath := path.Join(serverPath, "logs/latest.log")
logParser(logPath)
}
func handleCommands(eventArgs ...interface{}) {
user := eventArgs[0].(string)
str := eventArgs[1].(string)
log.WithFields(log.Fields{
"user": user,
"message": str,
}).Debug("Message received")
args := commands.ParseCommandArguments(str)
idx := strings.Index(str, " ")
var argString string
if idx == -1 {
argString = ""
} else {
argString = strings.TrimSpace(str[idx+1:])
}
var command string
if len(args) > 1 {
command, args = args[0], args[1:]
} else {
command = str
args = []string{}
}
// Find the channel that the message came from. Override and use State if enabled.
match := commands.Find("!", command, str)
if match == nil {
return
}
ctx := &commands.CommandContext{
User: user,
Prefix: "!",
Command: command,
ArgumentString: argString,
Arguments: args,
ArgumentCount: len(args),
Reply: func(text string) {
client.SendMessage(user, text)
},
}
go match.Call(ctx)
}