You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
2.9 KiB
Go

4 years ago
package sim
import (
"github.com/jordanorelli/astro-domu/internal/math"
"github.com/jordanorelli/astro-domu/internal/wire"
"github.com/jordanorelli/blammo"
)
4 years ago
// player is a player session in the simulation, eek
4 years ago
type player struct {
*blammo.Log
*room
4 years ago
name string
outbox chan wire.Response
pending []Request
avatar *entity
4 years ago
}
type Move math.Vec
func (Move) NetTag() string { return "move" }
4 years ago
func (m *Move) exec(r *room, p *player, seq int) result {
pos := p.avatar.Position
target := pos.Add(math.Vec(*m))
4 years ago
p.Info("running move for player %s from %v to %v", p.name, *m, target)
if !p.room.bounds.Contains(target) {
return result{reply: wire.Errorf("target cell (%d, %d) is out of bounds", target.X, target.Y)}
4 years ago
}
currentTile := r.getTile(pos)
nextTile := r.getTile(target)
if nextTile.here != nil {
return result{reply: wire.Errorf("target cell (%d, %d) is occupied", target.X, target.Y)}
4 years ago
}
currentTile.here, nextTile.here = nil, p.avatar
p.avatar.Position = target
e := wire.Entity{
ID: p.avatar.ID,
Position: p.avatar.Position,
Glyph: p.avatar.Glyph,
}
return result{reply: e, announce: e}
}
// SpawnPlayer is a request to spawn a player
type SpawnPlayer struct {
Outbox chan wire.Response
4 years ago
Name string
queued bool
}
var lastEntityID = 0
4 years ago
func (s *SpawnPlayer) exec(r *room, _ *player, seq int) result {
if !s.queued {
4 years ago
r.Info("spawn player requested for: %s", s.Name)
4 years ago
if _, ok := r.players[s.Name]; ok {
s.Outbox <- wire.ErrorResponse(seq, "a player is already logged in as %q", s.Name)
return result{}
}
lastEntityID++
avatar := &entity{
ID: lastEntityID,
Position: math.Vec{0, 0},
Glyph: '@',
behavior: doNothing{},
}
p := &player{
4 years ago
Log: r.Log.Child("players").Child(s.Name),
room: r,
4 years ago
name: s.Name,
outbox: s.Outbox,
pending: make([]Request, 0, 32),
avatar: avatar,
}
4 years ago
p.pending = append(p.pending, Request{Seq: seq, From: s.Name, Wants: s})
r.players[s.Name] = p
r.tiles[0].here = p.avatar
s.queued = true
return result{}
}
welcome := wire.Welcome{
Rooms: make(map[string]wire.Room),
Players: make(map[string]wire.Player),
}
ents := make(map[int]*wire.Entity)
for id, e := range r.allEntities() {
ents[id] = &wire.Entity{
ID: id,
Position: e.Position,
Glyph: e.Glyph,
}
}
welcome.Rooms[r.name] = wire.Room{
Name: r.name,
Bounds: r.bounds,
Entities: ents,
}
for _, p := range r.players {
welcome.Players[p.name] = wire.Player{
Name: p.name,
Avatar: p.avatar.ID,
Room: r.name,
}
}
return result{reply: welcome}
}
func (SpawnPlayer) NetTag() string { return "player/spawn" }
// PlayerSpawned is an announcement that a player has spawned
type PlayerSpawned struct {
4 years ago
Name string `json:"name"`
Position [2]int `json:"position"`
}
4 years ago
func (PlayerSpawned) NetTag() string { return "player/spawned" }
func init() {
wire.Register(func() wire.Value { return new(Move) })
}