diff --git a/db.go b/db.go index 0a47c46..adf4592 100644 --- a/db.go +++ b/db.go @@ -123,6 +123,6 @@ func randomPlanet() (*exoSystem, error) { } pick := rand.Intn(n) - planet := planetIndex[pick] - return &planet, nil + planet := planetIndex[pick] + return &planet, nil } diff --git a/errors.go b/errors.go index eec361c..33d9354 100644 --- a/errors.go +++ b/errors.go @@ -8,7 +8,7 @@ const ( E_Ok int = iota E_No_Data E_No_DB - E_No_Port + E_No_Port ) type errorGroup []error diff --git a/interactions.go b/interactions.go index 94fb070..221e923 100644 --- a/interactions.go +++ b/interactions.go @@ -1,6 +1,3 @@ package main -import ( -) - - +import () diff --git a/main.go b/main.go index 2eca770..1400b26 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,14 @@ package main import ( - "bufio" "fmt" + "io" + "math/rand" "net" "os" - "regexp" "strings" + "sync" + "time" ) var dataPath = "/projects/exo/expl.speck" @@ -30,30 +32,58 @@ func bail(status int, template string, args ...interface{}) { os.Exit(status) } -func handleConnection(conn net.Conn) { - namePattern := regexp.MustCompile(`^[[:alpha:]][[:alnum:]-_]{0,19}$`) - r := bufio.NewReader(conn) - fmt.Fprintf(conn, "what is your name, adventurer?\n") - name, err := r.ReadString('\n') - if err == nil { - name = strings.TrimSpace(name) - log_info("player connected: %v", name) - } else { - log_error("player failed to connect: %v", err) +func handleConnection(conn *Connection) { + var mu sync.Mutex + + defer conn.Close() + conn.Login() + + planet, err := randomPlanet() + if err != nil { + log_error("player %s failed to get random planet: %v", conn.PlayerName(), err) + return } - if !namePattern.MatchString(name) { - fmt.Fprintf(conn, "that name is illegal.\n") - } + fmt.Fprintf(conn, "you are on the planet %s\n", planet.name) + for { + line, err := conn.ReadString('\n') + switch err { + case io.EOF: + return + case nil: + break + default: + log_error("failed to read line from player %s: %v", conn.PlayerName(), err) + } + line = strings.TrimSpace(line) + parts := strings.Split(line, " ") + switch parts[0] { + case "scan": + for _, otherPlanet := range planetIndex { + if otherPlanet.name == planet.name { + continue + } + go func(p exoSystem) { + dist := planetDistance(*planet, p) + delay := time.Duration(int64(dist * 100000000)) + time.Sleep(delay) + mu.Lock() + fmt.Fprintf(conn, "PONG from planet %s (%v)\n", p.name, delay) + mu.Unlock() + }(otherPlanet) + } + case "broadcast": - planet, err := randomPlanet() - if err != nil { - log_error("player %s failed to get random planet: %v", name, err) - return - } - fmt.Fprintf(conn, "you are on the planet %s\n", planet.name) + case "quit": + return + default: + fmt.Fprintf(conn, "hmm I'm not sure I know that one.\n") + } + } } func main() { + rand.Seed(time.Now().UnixNano()) + setupDb() listener, err := net.Listen("tcp", ":9220") if err != nil { @@ -65,6 +95,6 @@ func main() { log_error("error accepting connection: %v", err) continue } - go handleConnection(conn) + go handleConnection(NewConnection(conn)) } } diff --git a/player.go b/player.go new file mode 100644 index 0000000..37c13b2 --- /dev/null +++ b/player.go @@ -0,0 +1,19 @@ +package main + +import ( + "regexp" +) + +var namePattern = regexp.MustCompile(`^[[:alpha:]][[:alnum:]-_]{0,19}$`) + +func ValidName(name string) bool { + return namePattern.MatchString(name) +} + +type Player struct { + name string +} + +func (p *Player) Load() { + +} diff --git a/session.go b/session.go new file mode 100644 index 0000000..642b358 --- /dev/null +++ b/session.go @@ -0,0 +1,50 @@ +package main + +import ( + "bufio" + "fmt" + "net" + "strings" +) + +type Connection struct { + net.Conn + *bufio.Reader + player Player +} + +func NewConnection(conn net.Conn) *Connection { + return &Connection{ + Conn: conn, + Reader: bufio.NewReader(conn), + } +} + +func (c *Connection) Login() { + for { + fmt.Fprintf(c, "what is your name, adventurer?\n") + name, err := c.ReadString('\n') + if err == nil { + name = strings.TrimSpace(name) + } else { + log_error("player failed to connect: %v", err) + return + } + if !ValidName(name) { + fmt.Fprintf(c, "that name is illegal.\n") + continue + } + log_info("player connected: %v", name) + c.player = Player{name: name} + break + } +} + +func (c *Connection) Close() error { + log_info("player disconnecting: %s", c.player.name) + return c.Conn.Close() +} + +func (c *Connection) PlayerName() string { + return c.player.name +}