func TestService_Rewind(t *testing.T) { s := entity.NewService() f := s.Frontend() // Accept all requests go (func() { for { var req entity.Request select { case req = <-f.Creates: case req = <-f.Updates: case req = <-f.Deletes: } s.AcceptRequest(req) } })() t0 := message.AbsoluteTick(1) // Create a new entity ent := message.NewEntity() ent.Position.X = 10 ent.Position.Y = 15 req := f.Add(ent, t0) req.Wait() created := req.(*entity.CreateRequest) id := created.Entity.Id if id == 0 { t.Fatal("Entity doesn't have an id after being added") } ent0 := s.Get(id) t1 := t0 + 5 // Update the entity update := message.NewEntity() update.Id = id update.Position.X = 33 update.Position.Y = 15 diff := &message.EntityDiff{Position: true} req = f.Update(update, diff, t1) req.Wait() // Rewind err := s.Rewind(s.GetTick() - t0) if err != nil { t.Fatal(err) } rewindEnt := s.Get(id) if rewindEnt.Position.X != ent0.Position.X { t.Fatal("Invalid rewind, expected position", ent0.Position.X, "but got", rewindEnt.Position.X) } }
func New(srv *server.Server, timeSrv *timeserver.Server) *Engine { // Create a new context ctx := message.NewServerContext() // Create the engine e := &Engine{ ctx: ctx, srv: srv, timeSrv: timeSrv, auth: auth.NewService(), clock: clock.NewService(), entity: entity.NewService(), action: action.NewService(), terrain: terrain.New(), config: game.DefaultConfig(), clients: make(map[int]*server.Client), brdStop: make(chan bool), listenStop: make(chan bool), listenTimeStop: make(chan bool), } // Set config if timeSrv != nil { e.config.TimeServerPort = uint16(timeSrv.Port()) } // Populate context ctx.Auth = e.auth ctx.Entity = e.entity.Frontend() ctx.Action = e.action.Frontend() ctx.Terrain = e.terrain ctx.Clock = e.clock ctx.Config = e.config // Initialize engine submodules e.mover = NewMover(e) // Set callbacks e.auth.LoginCallback = func(session *message.Session) { entity := session.Entity // Populate entity // TODO: default values are hardcoded entity.Position.BX = 20 entity.Position.BY = 20 entity.Type = game.PlayerEntity entity.Sprite = game.PlayerSprite entity.Attributes[game.HealthAttr] = game.Health(1000) entity.Attributes[game.CooldownOneAttr] = game.Cooldown(0) } return e }