added config file support
This commit is contained in:
parent
c7d5e4be87
commit
aabda1cc90
60
config.go
Normal file
60
config.go
Normal 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
|
||||
}
|
19
control.go
19
control.go
@ -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
38
game.go
@ -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
22
main.go
@ -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")
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user