Skip to content

Commit

Permalink
start
Browse files Browse the repository at this point in the history
  • Loading branch information
woodworker committed Nov 3, 2013
1 parent 54362cc commit c13a3d0
Show file tree
Hide file tree
Showing 9 changed files with 315 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Expand Up @@ -20,3 +20,6 @@ _cgo_export.*
_testmain.go

*.exe

.idea
*.iml
6 changes: 6 additions & 0 deletions doc.go
@@ -0,0 +1,6 @@
// berlin-mud project doc.go

/*
berlin-mud document
*/
package main
12 changes: 12 additions & 0 deletions game/level.go
@@ -0,0 +1,12 @@
package game

type Level struct {
Key string `xml:"key,attr"`
Name string `xml:"name"`
Directions []Direction `xml:"directions>direction"`
}

type Direction struct {
Station string `xml:"station,attr"`
Direction string `xml:",chardata"`
}
12 changes: 12 additions & 0 deletions game/player.go
@@ -0,0 +1,12 @@
package game

import "encoding/xml"

type Player struct {
XMLName xml.Name `xml:"player"`
Nickname string `xml:"nickname,attr"`
Gamename string `xml:"name"`
Position string `xml:"position,attr"`
PlayerType string `xml:"type"`
Ch chan string
}
110 changes: 110 additions & 0 deletions game/server.go
@@ -0,0 +1,110 @@
package game

import (
"encoding/xml"
"path/filepath"
"os"
"io/ioutil"
"log"
)

type Server struct {
name string
players map[string]Player
levels map[string]Level
workingdir string
}

func NewServer(servername string, serverdir string) *Server {
return &Server{
name: servername,
players: make(map[string]Player),
levels: make(map[string]Level),
workingdir: serverdir,
}
}

func (s *Server) LoadLevels() error {
log.Println("Loading levels ...")
levelWalker := func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
fileContent, fileIoErr := ioutil.ReadFile(path)
if fileIoErr != nil {
log.Printf("\n")
log.Printf("File %s could not be loaded\n", path)
log.Printf("%v",fileIoErr)
//return fileIoErr
return nil
}
level := Level{}
if xmlerr := xml.Unmarshal(fileContent, &level); xmlerr != nil {
log.Printf("\n")
log.Printf("File %s could not be Unmarshaled\n", path, xmlerr)
log.Printf("%v",xmlerr)
//return xmlerr
return nil
}
log.Printf(" loaded: %s", info.Name())
s.addLevel(level)
return nil
}

filepath.Walk(s.workingdir+"/static/levels/", levelWalker)
return nil
}

func (s *Server) LoadPlayer(playerName string) bool {
playerFileName := s.workingdir+"/static/player/"+playerName+".player"

log.Println("Loading player %s", playerFileName)

fileContent, fileIoErr := ioutil.ReadFile(playerFileName)
if fileIoErr != nil {
log.Printf("\n")
log.Printf("File %s could not be loaded\n", playerFileName)
log.Printf("%v",fileIoErr)
//return fileIoErr
return false
}

player := Player{}
if xmlerr := xml.Unmarshal(fileContent, &player); xmlerr != nil {
log.Printf("\n")
log.Printf("File %s could not be Unmarshaled\n", playerFileName, xmlerr)
log.Printf("%v",xmlerr)
//return xmlerr
return false
}
log.Printf(" loaded: %s", player.Gamename)
s.addPlayer(player)

return true
}

func (s *Server) addLevel(level Level) error {
s.levels[level.Key] = level
return nil
}

func (s *Server) addPlayer(player Player) error {
s.players[player.Nickname] = player
return nil
}

func (s *Server) GetPlayerByNick(nickname string) (Player, bool) {
player,ok := s.players[nickname]
return player, ok
}

func (s *Server) GetRoom(key string) (Level, bool) {
level,ok := s.levels[key]
return level, ok
}

func (s *Server) GetName() string {
return s.name
}


156 changes: 156 additions & 0 deletions main.go
@@ -0,0 +1,156 @@
package main

import (
"bufio"
"fmt"
"io"
"log"
"net"
"os"
"strings"
"github.com/woodworker/go-mud/game"
)

type Client struct {
conn net.Conn
nickname string
player game.Player
ch chan string
}

func main() {
workingdir, _ := os.Getwd()

log.Printf("Leveldir %s", workingdir+"/static/levels/")

server := game.NewServer("berlin-mud", workingdir)
server.LoadLevels()
log.Printf("%v", server)


ln, err := net.Listen("tcp", ":1337")
if err != nil {
fmt.Println(err)
os.Exit(1)
}

msgchan := make(chan string)
addchan := make(chan Client)
rmchan := make(chan Client)

go handleMessages(msgchan, addchan, rmchan)

for {
conn, err := ln.Accept()
if err != nil {
fmt.Println(err)
continue
}

go handleConnection(conn, msgchan, addchan, rmchan, server)
}
}

func (c Client) ReadLinesInto(ch chan<- string) {
bufc := bufio.NewReader(c.conn)
for {
line, err := bufc.ReadString('\n')
if err != nil {
break
}
ch <- fmt.Sprintf("%s: %s", c.player.Gamename, line)
}
}

func (c Client) WriteLinesFrom(ch <-chan string) {
for msg := range ch {
_, err := io.WriteString(c.conn, msg)
if err != nil {
return
}
}
}

func promptNick(c net.Conn, bufc *bufio.Reader) string {
io.WriteString(c, "What is your nick? ")
nick, _, _ := bufc.ReadLine()
return string(nick)
}

func handleConnection(c net.Conn, msgchan chan<- string, addchan chan<- Client, rmchan chan<- Client, server *game.Server) {
bufc := bufio.NewReader(c)
defer c.Close()

io.WriteString(c, fmt.Sprintf("\033[1;30;41mWelcome to the Go-Mud Server %s!\033[0m\n\r", server.GetName()))

var nickname string
for {
nickname = promptNick(c, bufc)
ok := server.LoadPlayer(nickname)
if ok == true {
break
}
}

player, playerLoaded := server.GetPlayerByNick(nickname)

if !playerLoaded {
log.Println("problem getting user object")
io.WriteString(c, "Problem getting user object\n")
return
}

client := Client{
conn: c,
nickname: player.Nickname,
player: player,
ch: make(chan string),
}

if strings.TrimSpace(client.nickname) == "" {
log.Println("invalid username")
io.WriteString(c, "Invalid Username\n")
return
}

// Register user
addchan <- client
defer func() {
msgchan <- fmt.Sprintf("User %s left the chat room.\n\r", client.nickname)
log.Printf("Connection from %v closed.\n", c.RemoteAddr())
rmchan <- client
}()
io.WriteString(c, fmt.Sprintf("Welcome, %s!\n\n\r", client.nickname))

location, locationLoaded:= server.GetRoom( client.player.Position );

if locationLoaded {
io.WriteString(c, fmt.Sprintf("You are at: \033[1;33;40m%s\033[m\n\n\r", location.Name))
}

msgchan <- fmt.Sprintf("New user %s has joined the chat room.\n\r", client.nickname)

// I/O
go client.ReadLinesInto(msgchan)
client.WriteLinesFrom(client.ch)
}

func handleMessages(msgchan <-chan string, addchan <-chan Client, rmchan <-chan Client) {
clients := make(map[net.Conn]chan<- string)

for {
select {
case msg := <-msgchan:
log.Printf("New message: %s", msg)
for _, ch := range clients {
go func(mch chan<- string) { mch <- "\033[1;33;40m" + msg + "\033[m" }(ch)
}
case client := <-addchan:
log.Printf("New client: %v\n", client.conn)
clients[client.conn] = client.ch
case client := <-rmchan:
log.Printf("Client disconnects: %v\n", client.conn)
delete(clients, client.conn)
}
}
}
6 changes: 6 additions & 0 deletions static/levels/alex.lvl
@@ -0,0 +1,6 @@
<station key="alex">
<name>Alexanderplatz</name>
<directions>
<direction station="jannowitzbruecke">East</direction>
</directions>
</station>
6 changes: 6 additions & 0 deletions static/levels/jannowitzbruecke.lvl
@@ -0,0 +1,6 @@
<station key="jannowitzbruecke">
<name>Jannowitzbrücke</name>
<directions>
<direction station="alex">West</direction>
</directions>
</station>
4 changes: 4 additions & 0 deletions static/player/woodworker.player
@@ -0,0 +1,4 @@
<player nickname="woodworker" position="alex">
<name>The Mighty WooDWorkeR</name>
<type>Geek</type>
</player>

0 comments on commit c13a3d0

Please sign in to comment.