Initial Commit

For some reason.
This commit is contained in:
Brian Buller 2014-12-21 13:30:42 -06:00
commit 6cc194a5d1
5 changed files with 450 additions and 0 deletions

134
mc_man.go Normal file
View File

@ -0,0 +1,134 @@
package main
import (
"fmt"
"github.com/br0xen/mc_man/util"
"log"
"os"
"os/exec"
"strings"
)
func main() {
// Load the Config
util.LoadConfig()
xmxVal := "1024M"
xmsVal := "1024M"
args := os.Args[1:]
if len(args) > 0 {
if args[0] == "-help" {
fmt.Println("Usage: mc_man <Xmx Value> <Xms Value>")
fmt.Println(" <Xmx Value> - The Maximum Memory Allocation Pool for the JVM")
fmt.Println(" <Xms Value> - The Initial Memory Allocation Pool")
os.Exit(0)
}
if len(args) > 0 {
xmxVal = args[0]
if len(args) > 1 {
xmsVal = args[1]
}
}
}
// The minecraft server command
cmd := exec.Command("java", "-Xmx"+xmxVal, "-Xms"+xmsVal, "-jar", "minecraft_server.jar", "nogui")
// Control StdIn
stdin, err := cmd.StdinPipe()
if err != nil {
log.Fatal(err)
}
// Pipe the process' stdout to stdout for monitoring
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatal(err)
}
// Kick off the process
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
// Build a string channel for stdout
ch := make(chan string)
// And a routine to keep the channel updated
go func() {
buf := make([]byte, 1024)
for {
n, err := stdout.Read(buf)
if n != 0 {
// Something there throw it into the channel
ch <- string(buf[:n])
}
if err != nil {
// Error, break out of loop
break
}
}
fmt.Println("mc_man stopped")
close(ch)
}()
listen_for := ""
listen_for_user := ""
// The forever loop to monitor the channel
loop:
for {
s, ok := <-ch
if !ok {
break loop
}
m := util.NewMessage(s)
// First check for anything we're listening for
if listen_for != "" && strings.Contains(m.Text, listen_for) {
r := strings.Split(m.Text, listen_for)
if len(r) > 0 {
p_str := r[1]
p_str = strings.Replace(p_str, ",", "", -1)
util.SetHome(listen_for_user, p_str)
stdin.Write([]byte("tell " + listen_for_user + " Set your home to " + p_str))
listen_for = ""
listen_for_user = ""
}
} else {
if m.IsStopRequest() {
stdin.Write([]byte("stop\n"))
} else if m.IsHomeRequest() {
home_str, found := util.GetHome(m.User.Name)
if found {
stdin.Write([]byte("tp " + m.User.Name + " " + home_str + "\n"))
}
} else if m.IsSetHomeRequest() {
listen_for = "Teleported " + m.User.Name + " to "
listen_for_user = m.User.Name
stdin.Write([]byte("tp " + m.User.Name + " ~ ~ ~\n"))
} else if m.IsVisitRequest() {
visiting_user, err := m.VisitingUser()
if !err {
fmt.Printf("\x1b[31;1m%s requested a tp visit to %s\x1b[0m\n", m.User.Name, visiting_user)
porch_str, found := util.GetPorch(visiting_user)
fmt.Printf(">>> Porch String: " + porch_str)
if found {
stdin.Write([]byte("tp " + m.User.Name + " " + porch_str + "\n"))
} else {
stdin.Write([]byte("tell " + m.User.Name + " Couldn't find that user's porch 1\n"))
}
} else {
stdin.Write([]byte("tell " + m.User.Name + " Couldn't find that user's porch 2\n"))
}
} else if m.IsSetPorchRequest() {
listen_for = "Teleported " + m.User.Name + " to "
listen_for_user = m.User.Name
stdin.Write([]byte("tp " + m.User.Name + " ~ ~ ~\n"))
} else {
// fmt.Printf("\x1b[34;1m%s\x1b[0m", m.Output())
}
}
fmt.Printf("\x1b[34;1m%s\x1b[0m", m.Output())
}
}

160
util/config.go Normal file
View File

@ -0,0 +1,160 @@
package util
import (
"fmt"
"github.com/antonholmquist/jason"
"io/ioutil"
// "log"
// "os"
// "bytes"
"strings"
)
type Config struct {
// The JSON object of what was read
LoadedJson jason.Object
Options jason.Object
FeatureTPHome bool
FeatureTPVisit bool
Users []*User
U User
}
var c *Config
func LoadConfig() {
c = new(Config)
config_str, err := ioutil.ReadFile("mc_man.config")
if err == nil {
j, _ := jason.NewObjectFromBytes(config_str)
o, _ := j.GetObjectArray("options")
for _, option := range o {
opt_name, _ := option.GetString("name")
opt_enabled, _ := option.GetBoolean("enabled")
if opt_name == "home" {
c.FeatureTPHome = opt_enabled
} else if opt_name == "visit" {
c.FeatureTPVisit = opt_enabled
}
}
c.Users = make([]*User, 1)
u, _ := j.GetObjectArray("users")
for _, user := range u {
user_name, err := user.GetString("name")
if err == nil && user_name != "" {
user_home, _ := user.GetString("home")
user_porch, _ := user.GetString("porch")
us := NewUser(user_name)
// TODO: Check if this user is an op on the server
us.Home = user_home
us.Porch = user_porch
c.Users = append(c.Users, us)
c.U = *us
}
}
fmt.Printf("Loaded %d Users", len(c.Users))
}
}
func WriteConfig() {
// Generate the JSON string for the config file
d := "{\"options\":["
// Output options array
d = d + "{\"name\":\"home\",\"enabled\":"
if c.FeatureTPHome {
d = d + "true"
} else {
d = d + "false"
}
d = d + "},{\"name\":\"visit\",\"enabled\":"
if c.FeatureTPVisit {
d = d + "true"
} else {
d = d + "false"
}
d = d + "}],\"users\":["
d = d + c.U.ToJSONString()
// Output users array
/*
num_users := len(c.Users)
fmt.Printf("Number of Users: %d", num_users)
for i := 0; i < num_users; i++ {
user := c.Users[i]
// for _, user := range c.Users {
fmt.Println(d)
num_users--
d = d + user.ToJSONString()
if user.Name != "" {
if num_users > 0 {
d = d + ","
}
}
}
*/
d = d + "]}"
do := []byte(d)
ioutil.WriteFile("mc_man.config", do, 0644)
}
func SetHome(user string, loc string) {
/*
u, idx := FindUser(user)
if idx == -1 {
u = NewUser(user)
c.Users = append(c.Users, u)
idx = len(c.Users) - 1
}
u.Home = strings.Replace(loc, "\n", "", -1)
// Replace the user in the Users array
c.Users[idx] = u
*/
c.U.Home = strings.Replace(loc, "\n", "", -1)
WriteConfig()
}
func GetHome(user string) (string, bool) {
/*
u, idx := FindUser(user)
if idx == -1 || u.Home == "" {
return "", false
}
*/
return c.U.Home, true
}
func SetPorch(user string, loc string) {
/*
u, idx := FindUser(user)
if idx == -1 {
u = NewUser(user)
c.Users = append(c.Users, u)
idx = len(c.Users) - 1
}
u.Porch = strings.Replace(loc, "\n", "", -1)
c.Users[idx] = u
*/
c.U.Porch = strings.Replace(loc, "\n", "", -1)
WriteConfig()
}
func GetPorch(user string) (string, bool) {
/*
u, idx := FindUser(user)
if idx > -1 || u.Porch == "" {
return "", false
}
return u.Porch, true
*/
return c.U.Porch, true
}
func FindUser(name string) (*User, int) {
for i, user := range c.Users {
if user.Name == name {
return user, i
}
}
return nil, -1
}

94
util/message.go Normal file
View File

@ -0,0 +1,94 @@
package util
import (
//"fmt"
"regexp"
"strings"
)
type Message struct {
User *User
Text string
IsStopRequest func() bool
IsHomeRequest func() bool
IsSetHomeRequest func() bool
IsVisitRequest func() bool
IsSetPorchRequest func() bool
VisitingUser func() (string, bool)
Output func() string
}
func NewMessage(t string) *Message {
m := new(Message)
msg_user := regexp.MustCompile("<[^>]+>")
tmpUser := msg_user.FindString(t)
tmpUser = strings.Replace(tmpUser, "<", "", -1)
tmpUser = strings.Replace(tmpUser, ">", "", -1)
m.User = NewUser(tmpUser)
if tmpUser == "br0xen" {
m.User.IsOp = true
}
m.Text = t
if m.User.Name != "" {
res := strings.Split(t, "<"+m.User.Name+"> ")
if len(res) > 0 {
m.Text = res[1]
}
}
m.IsStopRequest = func() bool {
return (m.User.IsOp && m.Text == "!stop\n")
}
m.IsHomeRequest = func() bool {
if m.User.Name != "" {
return (m.Text == "!home\n")
} else {
return false
}
}
m.IsSetHomeRequest = func() bool {
if m.User.Name != "" {
return (m.Text == "!set home\n")
} else {
return false
}
}
m.IsSetPorchRequest = func() bool {
if m.User.Name != "" {
return (m.Text == "!set porch\n")
} else {
return false
}
}
m.IsVisitRequest = func() bool {
if m.User.Name != "" {
return strings.HasPrefix(m.Text, "!visit ")
} else {
return false
}
}
m.VisitingUser = func() (string, bool) {
if m.IsVisitRequest() {
s := strings.Replace(m.Text, "!visit ", "", -1)
s = strings.Replace(s, "\n", "", -1)
return s, false
}
return "", true
}
m.Output = func() string {
if m.User.Name != "" {
return "<" + m.User.Name + "> " + m.Text
} else {
return m.Text
}
}
return m
}

41
util/message_manager.go Normal file
View File

@ -0,0 +1,41 @@
package util
import (
"strings"
)
type MessageManager struct {
/* Process takes a string and returns whether
* we did anything with that string or not
*/
Process func(inp string) bool
/* listeners is an array of functions that
* tell the manager how to listen for specific
* text and what to do if we receive it.
* Each listener returns true if the input was
* "consumed" (i.e. - Don't send to any more
* listeners)
*/
listeners []func(inp string) bool
/* tempListeners is an array of functions that
* work the same as 'listeners', but these are
* just temporary and higher priority than
* 'listeners'
*/
tempListeners []func(inp string) bool
}
func NewManager() *MessageManager {
mm := new(MessageManager)
mm.Process = func(inp string) bool {
// TODO: send to temp listeners
for i, listener := range listeners {
if listener(inp) {
return true
}
}
}
return mm
}

21
util/user.go Normal file
View File

@ -0,0 +1,21 @@
package util
type User struct {
Name string
IsOp bool
Home string
Porch string
ToJSONString func() string
}
func NewUser(nm string) *User {
m := new(User)
m.Name = nm
m.IsOp = false
m.Home = ""
m.Porch = ""
m.ToJSONString = func() string {
return "{\"name\":\"" + m.Name + "\",\"home\":\"" + m.Home + "\",\"porch\":\"" + m.Porch + "\"}"
}
return m
}