package main import ( "bufio" "fmt" "io" "os/exec" "regexp" "strings" "time" ) var ( mcOut io.Reader mcIn io.Writer mcStop = false mcLoaded = false mcRebooting = false mcWBRunning = false ) func (u User) McWhitelist() { mcCommand(fmt.Sprintf("whitelist add %+v", u.McUser)) mcCommand(fmt.Sprintf("nicknames %+v %+v", u.McUser, u.Email)) } func configureMinecraft() { log.LogInfo("Starting MinecraftServer") server := exec.Command("screen", "-r", "1234") mcIn, _ = server.StdinPipe() mcOut, _ = server.StdoutPipe() mcErr, _ := server.StderrPipe() mcErrScan := bufio.NewScanner(mcErr) server.Start() defer server.Wait() go listenOut() for mcErrScan.Scan() { if mcStop { break } log.LogError(mcErrScan.Text()) } } func handleMcOnline(s string) { log.LogDebug("A user has come online or gone offline.") s = strings.Replace(s, "&e", "", -1) var u User parts := strings.Split(s, " ") log.LogDebug(fmt.Sprintf("%+v", parts)) if parts[2] == "UUID" { log.LogDebug(fmt.Sprintf("User %+v detected.", parts[5])) if serverRebooting { mcCommand(fmt.Sprintf("kick %+v Server reboot pending.", parts[5])) } //mcCommand(fmt.Sprintf("kick %+v Server currently unavailable.", parts[5])) u.McUser = parts[5] u.Retrieve() if u.Email == "" { u.Email = u.McUser u.McUser = "" u.Retrieve() if u.McUser == "" { sendAdminDiscordMessage(fmt.Sprintf("Unable to verify %+v", parts[5])) mcCommand(fmt.Sprintf("kick %+v Verified SITNET not found. Admins have been notified.", parts[5])) return } } else if u.Email != parts[5] { mcCommand(fmt.Sprintf("lp user %+v parent add player", u.McUser)) mcCommand(fmt.Sprintf("nicknames %+v %+v", u.McUser, u.Email)) } for _, v := range onlineUsers { if v.Email == u.Email { return } } onlineUsers = append(onlineUsers, u) } else { log.LogDebug(fmt.Sprintf("User %+v detected.", parts[2])) u.McUser = parts[2] u.Retrieve() for k, v := range onlineUsers { log.LogDebug(fmt.Sprintf("v.McUser: %+v, parts[2]: %+v", v.McUser, parts[2])) if v.McUser == parts[2] || v.Email == parts[2] { onlineUsers[k] = onlineUsers[len(onlineUsers)-1] // Copy last element to index i. onlineUsers = onlineUsers[:len(onlineUsers)-1] // Truncate slice. } } } u.Write() log.LogDebug(fmt.Sprintf("Online users: %+v", onlineUsers)) if len(onlineUsers) == 0 && !config.WbFinished { log.LogInfo("The last user has logged out.") mcWorldBuilderToggle(true) } else { mcWorldBuilderToggle(false) } } func listenOut() { outScan := bufio.NewScanner(mcOut) var re = regexp.MustCompile(`INFO\]: <(.*?)> (.*)`) for outScan.Scan() { if mcStop { break } output := outScan.Text() go log.LogInfo(fmt.Sprintf("server.jar: %+v", output)) if !mcLoaded { if strings.Contains(output, "For help, type \"help\"") { mcLoaded = true sendDiscordMessage("Minecraft server is now available.") mcWorldBuilderToggle(true) } continue } if strings.Contains(output, "UUID of player") || strings.Contains(output, "left the game") { go handleMcOnline(output) } match := re.FindStringSubmatch(output) if match != nil { if match[1] != "Server" { var u User u.McUser = match[1] u.Retrieve() if u.Email == "" { u.McUser = "" u.Email = match[1] u.Retrieve() u.Write() } else if u.Email != match[1] { mcCommand(fmt.Sprintf("nicknames %+v %+v", u.McUser, u.Email)) } log.LogDebug(fmt.Sprintf("Minecraft message from retrieved user %+v", u)) go sendDiscordMessage(fmt.Sprintf("[%s]: %s", u.Email, match[2])) continue } } else if mcLoaded && !strings.Contains(output, " INFO]: [Server] [") && !strings.Contains(output, "[WorldBorder]") { go sendAdminDiscordMessage(output) } } } func mcWorldBuilderToggle(b bool) { log.LogDebug("World builder toggled") if b && !mcWBRunning { log.LogDebug("Building world!") mcCommand("wb world fill 500 300 false") mcCommand("wb fill confirm") mcWBRunning = true return } else if mcWBRunning { log.LogDebug("Not building world!") mcCommand("wb fill cancel") mcWBRunning = false } } func mcSay(message string) { mcCommand(fmt.Sprintf("say %+v", mcMention(message))) } func mcMention(s string) string { var ret string if !strings.Contains(s, "@") { return s } parts := strings.Split(s, " ") for _, part := range parts { if strings.HasPrefix(part, "<@!") { var u User u.DiscordID = strings.Replace(strings.Replace(part, "<@!", "", -1), ">", "", -1) u.Retrieve() ret += "@" ret += u.Email } else { ret += part } ret += " " log.LogDebug(ret) } return ret } func mcCommand(message string) { mcIn.Write([]byte(message)) mcIn.Write([]byte("\n")) } func mcReboot(when int, reminders int) { if mcRebooting { return } mcRebooting = true untilReboot := time.Duration(when) * time.Minute rebootTime := time.Now().Add(untilReboot) var untilReminder time.Duration if reminders != 0 { untilReminder = time.Duration(when / reminders) } for { mcSay(fmt.Sprintf("A reboot has been scheduled for %+v", untilReboot)) if reminders > 0 { reminders-- time.Sleep(untilReminder) continue } time.Sleep(time.Until(rebootTime)) mcExit() discordExit() } } func mcExit() { log.LogCritical("Closing Minecraft (issuing command `stop`)") mcCommand("stop") mcStop = true mcLoaded = false }