fixing up entity ID clashes

master
Jordan Orelli 4 years ago
parent 804943b5ab
commit b32dfb8359

@ -3,8 +3,7 @@ package sim
import "github.com/jordanorelli/astro-domu/internal/wire" import "github.com/jordanorelli/astro-domu/internal/wire"
type Effect interface { type Effect interface {
//wire.Value exec(*world, *room, *player, int) result
exec(*room, *player, int) result
} }
type result struct { type result struct {

@ -3,7 +3,6 @@ package sim
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"math/rand"
"time" "time"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
@ -49,12 +48,17 @@ func (p *player) start(c chan Request, conn *websocket.Conn, r *room) {
} }
welcome.Players[p.name] = wp welcome.Players[p.name] = wp
} }
p.Info("sending welcome to outbox")
p.outbox <- wire.Response{Re: 1, Body: welcome} p.outbox <- wire.Response{Re: 1, Body: welcome}
p.Info("sent welcome, starting loops")
go p.readLoop(c, conn) go p.readLoop(c, conn)
go p.runLoop(conn) go p.runLoop(conn)
} }
func (p *player) readLoop(c chan Request, conn *websocket.Conn) { func (p *player) readLoop(c chan Request, conn *websocket.Conn) {
p.Info("readLoop started")
defer p.Info("readLoop ended")
for { for {
_, b, err := conn.ReadMessage() _, b, err := conn.ReadMessage()
if err != nil { if err != nil {
@ -69,10 +73,10 @@ func (p *player) readLoop(c chan Request, conn *websocket.Conn) {
p.Error("unable to parse request: %v", err) p.Error("unable to parse request: %v", err)
continue continue
} }
// sn.Info("received message of type %T", req.Body)
effect, ok := req.Body.(Effect) effect, ok := req.Body.(Effect)
if !ok { if !ok {
p.Error("request is not an effect, is %T", req.Body)
continue continue
} }
c <- Request{ c <- Request{
@ -81,10 +85,12 @@ func (p *player) readLoop(c chan Request, conn *websocket.Conn) {
Wants: effect, Wants: effect,
} }
} }
} }
func (p *player) runLoop(conn *websocket.Conn) { func (p *player) runLoop(conn *websocket.Conn) {
p.Info("runLoop started")
defer p.Info("runLoop ended")
for { for {
select { select {
case res := <-p.outbox: case res := <-p.outbox:
@ -133,12 +139,12 @@ func sendResponse(conn *websocket.Conn, res wire.Response) error {
type spawnPlayer struct{} type spawnPlayer struct{}
func (s spawnPlayer) exec(r *room, p *player, seq int) result { func (s spawnPlayer) exec(w *world, r *room, p *player, seq int) result {
for n, t := range r.tiles { for n, t := range r.tiles {
if t.here == nil { if t.here == nil {
x, y := n%r.Width, n/r.Width x, y := n%r.Width, n/r.Width
e := entity{ e := entity{
ID: rand.Intn(9000), ID: <-w.nextID,
Position: math.Vec{x, y}, Position: math.Vec{x, y},
Glyph: '@', Glyph: '@',
behavior: doNothing{}, behavior: doNothing{},
@ -155,7 +161,7 @@ type Move math.Vec
func (Move) NetTag() string { return "move" } func (Move) NetTag() string { return "move" }
func (m *Move) exec(r *room, p *player, seq int) result { func (m *Move) exec(w *world, r *room, p *player, seq int) result {
pos := p.avatar.Position pos := p.avatar.Position
target := pos.Add(math.Vec(*m)) target := pos.Add(math.Vec(*m))
p.Info("running move for player %s from %v to %v", p.name, *m, target) p.Info("running move for player %s from %v to %v", p.name, *m, target)

@ -1,8 +1,6 @@
package sim package sim
import ( import (
"time"
"github.com/jordanorelli/astro-domu/internal/math" "github.com/jordanorelli/astro-domu/internal/math"
"github.com/jordanorelli/astro-domu/internal/wire" "github.com/jordanorelli/astro-domu/internal/wire"
"github.com/jordanorelli/blammo" "github.com/jordanorelli/blammo"
@ -16,38 +14,6 @@ type room struct {
players map[string]*player players map[string]*player
} }
func (r *room) update(dt time.Duration) {
for _, p := range r.players {
if p.pending == nil {
continue
}
req := p.pending
p.pending = nil
res := req.Wants.exec(r, p, req.Seq)
if res.reply != nil {
p.outbox <- wire.Response{Re: req.Seq, Body: res.reply}
} else {
p.outbox <- wire.Response{Re: req.Seq, Body: wire.OK{}}
}
}
for _, t := range r.tiles {
if t.here != nil {
t.here.update(dt)
}
}
frame := wire.Frame{
Entities: r.allEntities(),
Players: r.playerAvatars(),
}
for _, p := range r.players {
p.outbox <- wire.Response{Body: frame}
}
}
func (r *room) allEntities() map[int]wire.Entity { func (r *room) allEntities() map[int]wire.Entity {
all := make(map[int]wire.Entity, 4) all := make(map[int]wire.Entity, 4)
for _, t := range r.tiles { for _, t := range r.tiles {

@ -27,7 +27,7 @@ func (s *Server) Start(host string, port int) error {
} }
s.world = newWorld(s.Log.Child("world")) s.world = newWorld(s.Log.Child("world"))
go s.world.run(30) go s.world.run(2)
addr := fmt.Sprintf("%s:%d", host, port) addr := fmt.Sprintf("%s:%d", host, port)
lis, err := net.Listen("tcp", addr) lis, err := net.Listen("tcp", addr)

@ -15,6 +15,7 @@ type world struct {
*blammo.Log *blammo.Log
inbox chan Request inbox chan Request
connect chan connect connect chan connect
nextID chan int
done chan bool done chan bool
lastEntityID int lastEntityID int
@ -51,12 +52,25 @@ func newWorld(log *blammo.Log) *world {
inbox: make(chan Request), inbox: make(chan Request),
connect: make(chan connect), connect: make(chan connect),
players: make(map[string]*player), players: make(map[string]*player),
nextID: make(chan int),
} }
} }
func (w *world) run(hz int) { func (w *world) run(hz int) {
defer w.Info("simulation has exited run loop") defer w.Info("simulation has exited run loop")
go func() {
lastID := 1
for {
select {
case <-w.done:
return
case w.nextID <- lastID:
lastID++
}
}
}()
period := time.Second / time.Duration(hz) period := time.Second / time.Duration(hz)
w.Info("starting world with a tick rate of %dhz, frame duration of %v", hz, period) w.Info("starting world with a tick rate of %dhz, frame duration of %v", hz, period)
ticker := time.NewTicker(period) ticker := time.NewTicker(period)
@ -66,9 +80,12 @@ func (w *world) run(hz int) {
select { select {
case c := <-w.connect: case c := <-w.connect:
w.register(c) w.register(c)
w.Info("finished registration for: %v", c)
case req := <-w.inbox: case req := <-w.inbox:
w.Info("read request off of inbox: %v", req)
w.handleRequest(req) w.handleRequest(req)
w.Info("finished handling request: %v", req)
case <-ticker.C: case <-ticker.C:
w.tick(time.Since(lastTick)) w.tick(time.Since(lastTick))
@ -123,6 +140,7 @@ func (w *world) register(c connect) {
foyer.players[c.login.Name] = &p foyer.players[c.login.Name] = &p
w.players[c.login.Name] = &p w.players[c.login.Name] = &p
w.Info("starting player...")
p.start(w.inbox, c.conn, foyer) p.start(w.inbox, c.conn, foyer)
} }
@ -134,7 +152,39 @@ func (w *world) stop() error {
} }
func (w *world) tick(d time.Duration) { func (w *world) tick(d time.Duration) {
// run all player effects
for _, r := range w.rooms {
for _, p := range r.players {
if p.pending == nil {
continue
}
req := p.pending
p.pending = nil
res := req.Wants.exec(w, r, p, req.Seq)
if res.reply != nil {
p.outbox <- wire.Response{Re: req.Seq, Body: res.reply}
} else {
p.outbox <- wire.Response{Re: req.Seq, Body: wire.OK{}}
}
}
}
// run all object effects
for _, r := range w.rooms { for _, r := range w.rooms {
r.update(d) for _, t := range r.tiles {
if t.here != nil {
t.here.update(d)
}
}
frame := wire.Frame{
Entities: r.allEntities(),
Players: r.playerAvatars(),
}
for _, p := range r.players {
p.outbox <- wire.Response{Body: frame}
}
} }
} }

Loading…
Cancel
Save