func (s *Service) Rewind(dt message.AbsoluteTick) error { if dt > s.tick { return errors.New(fmt.Sprintf("Cannot rewind by %d: negative tick", dt)) } else if dt < 0 { return errors.New(fmt.Sprintf("Cannot rewind by %d: negative rewind", dt)) } else if dt == 0 { return nil } target := s.tick - dt // Browse deltas list backward (from newer to older) for e := s.deltas.LastBefore(s.tick); e != nil; e = e.Prev() { d := e.Value.(*Delta) if d.tick <= target { // Reached target, stop here break } // Revert delta if d.From != nil { current := s.Get(d.EntityId) if current != nil { // The entity has been updated, revert update diff := d.Diff if diff == nil { diff = message.NewFilledEntityDiff(true) } current.ApplyDiff(diff, d.From) } else { // The entity has been deleted, restore it s.entities[d.EntityId] = d.From } } else { // The entity has been created, delete it delete(s.entities, d.EntityId) } if s.frontend != nil { s.frontend.locker.Lock() s.frontend.deltas.Insert(d.Inverse().(*Delta)) s.frontend.locker.Unlock() } } s.tick = target return nil }
// Deep copy this entity. func (e *Entity) Copy() *Entity { copy := New() copy.Id = e.Id copy.ApplyDiff(message.NewFilledEntityDiff(true), e) return copy }