Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
54362cc
commit c13a3d0
Showing
9 changed files
with
315 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,3 +20,6 @@ _cgo_export.* | |
_testmain.go | ||
|
||
*.exe | ||
|
||
.idea | ||
*.iml |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// berlin-mud project doc.go | ||
|
||
/* | ||
berlin-mud document | ||
*/ | ||
package main |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<station key="alex"> | ||
<name>Alexanderplatz</name> | ||
<directions> | ||
<direction station="jannowitzbruecke">East</direction> | ||
</directions> | ||
</station> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<station key="jannowitzbruecke"> | ||
<name>Jannowitzbrücke</name> | ||
<directions> | ||
<direction station="alex">West</direction> | ||
</directions> | ||
</station> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<player nickname="woodworker" position="alex"> | ||
<name>The Mighty WooDWorkeR</name> | ||
<type>Geek</type> | ||
</player> |