added config file support

This commit is contained in:
Stephen McQuay 2013-11-13 20:38:57 -08:00
parent c7d5e4be87
commit aabda1cc90
5 changed files with 110 additions and 36 deletions

60
config.go Normal file
View File

@ -0,0 +1,60 @@
package main
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"log"
"os"
"os/user"
"strings"
)
type Config struct {
Tick int `json:"tick"` // ms
Timescale float32 `json:"timescale"`
Width int `json:"width"`
Height int `json:"height"`
Obstacles int `json:"obstacles"`
}
const (
TICK = 60
TIMESCALE = 1.0
WIDTH = 800
HEIGHT = 550
OBSTACLES = 5
)
func loadConfig(filename string) (Config, error) {
c := Config{}
u, err := user.Current()
if err != nil {
return c, err
}
if len(filename) > 1 && filename[:2] == "~/" {
filename = strings.Replace(filename, "~", u.HomeDir, 1)
}
if _, err := os.Stat(filename); os.IsNotExist(err) {
log.Printf("%+v not found, using defaults", filename)
return Config{
Tick: TICK,
Timescale: TIMESCALE,
Width: WIDTH,
Height: HEIGHT,
Obstacles: OBSTACLES,
}, nil
} else {
log.Printf("found config file: %s", filename)
f, err := ioutil.ReadFile(filename)
if err != nil {
return c, err
}
err = json.Unmarshal(f, &c)
if err != nil {
return c, errors.New(fmt.Sprintf("config parse error: %s", err))
}
}
return c, nil
}

View File

@ -20,7 +20,8 @@ func startGame(w http.ResponseWriter, req *http.Request) {
log.Println("asked to create a game")
requested_game_name := idg.Hash()
width, height := float32(*width), float32(*height)
width, height := float32(conf.Width), float32(conf.Height)
tick := conf.Tick
// here we determine if we are going to run with defaults or pick them off
// a posted json blob
@ -30,12 +31,13 @@ func startGame(w http.ResponseWriter, req *http.Request) {
log.Printf("unable to read request body:", err)
}
req.Body.Close()
conf := struct {
With float32 `json:"width"`
cfg := struct {
Width float32 `json:"width"`
Height float32 `json:"height"`
Name string `json:"name"`
Tick int `json:"tick"`
}{}
err = json.Unmarshal(body, &conf)
err = json.Unmarshal(body, &cfg)
if err != nil {
NewFailure(err.Error())
if err := json.NewEncoder(w).Encode(NewFailure(err.Error())); err != nil {
@ -43,15 +45,16 @@ func startGame(w http.ResponseWriter, req *http.Request) {
}
return
}
requested_game_name = conf.Name
width = conf.With
height = conf.Height
requested_game_name = cfg.Name
width = cfg.Width
height = cfg.Height
tick = cfg.Tick
}
g := games.get(requested_game_name)
if g == nil {
log.Printf("Game '%s' non-existant; making it now", requested_game_name)
g = NewGame(requested_game_name, width, height)
g = NewGame(requested_game_name, width, height, tick)
go g.run()
games.add(g)
} else {

38
game.go
View File

@ -80,26 +80,28 @@ type game struct {
kill chan bool
repair_hp int
repair_rate float32
tick_duration int
}
func NewGame(id string, width, height float32) *game {
func NewGame(id string, width, height float32, tick int) *game {
g := &game{
id: id,
register: make(chan *player),
unregister: make(chan *player, maxPlayer),
projectiles: make(map[*Projectile]bool),
splosions: make(map[*Splosion]bool),
obstacles: GenerateObstacles(*obstacle_count, width, height),
players: make(map[*player]bool),
turn: 0,
width: width,
height: height,
spectators: make(map[*Spectator]bool),
sregister: make(chan *Spectator),
sunregister: make(chan *Spectator),
kill: make(chan bool, maxPlayer),
repair_hp: 5,
repair_rate: 3.0,
id: id,
register: make(chan *player),
unregister: make(chan *player, maxPlayer),
projectiles: make(map[*Projectile]bool),
splosions: make(map[*Splosion]bool),
obstacles: GenerateObstacles(conf.Obstacles, width, height),
players: make(map[*player]bool),
turn: 0,
width: width,
height: height,
spectators: make(map[*Spectator]bool),
sregister: make(chan *Spectator),
sunregister: make(chan *Spectator),
kill: make(chan bool, maxPlayer),
repair_hp: 5,
repair_rate: 3.0,
tick_duration: tick,
}
return g
}
@ -251,7 +253,7 @@ func (g *game) sendUpdate(payload *Boardstate) {
func (g *game) run() {
var t0, t1 time.Time
ticker := time.NewTicker(time.Duration(*tick) * time.Millisecond)
ticker := time.NewTicker(time.Duration(conf.Tick) * time.Millisecond)
for {
select {
case <-g.kill:

22
main.go
View File

@ -13,25 +13,23 @@ import (
)
var addr = flag.String("addr", ":8666", "http service address")
var tick = flag.Int("tick", 60, "")
var timescale = flag.Float64("timescale", 1, "time scale factor")
var verbose = flag.Bool("verbose", false, "")
var width = flag.Float64("width", 800, "width of field")
var height = flag.Float64("height", 550, "height of field")
var obstacle_count = flag.Int("obstacles", 5, "how many obstacles")
var debug = flag.Bool("debug", false, "automatically create games if they don't exist")
var profile = flag.String("pprof", "", "if specified will run with pprof")
var netprofile = flag.Bool("netprof", false, "if specified will run with net/http/pprof")
var debug = flag.Bool("debug", false, "automatically create games if they don't exist")
var verbose = flag.Bool("verbose", false, "")
var config = flag.String("config", "~/.config/hackerbots/config.json", "location of config file")
var delta float32
var idg *IdGenerator
var conf Config
// This is the main, global collection of games
var games MapLock
func main() {
log.Printf("Starting Server...")
var err error
rand.Seed(time.Now().UnixNano())
flag.Parse()
@ -51,7 +49,13 @@ func main() {
games = MapLock{m: make(map[string]*game)}
idg = NewIdGenerator()
delta = (float32(*tick) / 1000.0) * float32(*timescale)
conf, err = loadConfig(*config)
if err != nil {
log.Fatal(err)
}
log.Printf("config: %+v", conf)
delta = (float32(conf.Tick) / 1000.0) * float32(conf.Timescale)
sm := http.NewServeMux()
@ -62,7 +66,7 @@ func main() {
sm.HandleFunc("/game/stop/", stopGame)
sm.HandleFunc("/fuck/shit/up/", killServer)
err := http.ListenAndServe(*addr, sm)
err = http.ListenAndServe(*addr, sm)
if err != nil {
log.Fatal("unable to start server")
}

View File

@ -125,7 +125,12 @@ func addPlayer(ws *websocket.Conn) {
if game == nil {
force := *debug
if force {
game = NewGame(gid.Id, float32(*width), float32(*height))
game = NewGame(
gid.Id,
float32(conf.Width),
float32(conf.Height),
conf.Tick,
)
go game.run()
games.add(game)
} else {