private static void _recordPositionFactory_DoWork(object sender, TrackedPosition pos)
 {
     try
     {
         using (TrackedPositionContext db = new TrackedPositionContext())
         {
             db.Positions.Add(pos);
             db.SaveChanges();
         }
     }
     catch (DbEntityValidationException e)
     {
         ProcessEntityException(e);
         throw;
     }
 }
        public static void RewindPlayersBlocks(Players.Player player)
        {
            foreach (var colony in player.Colonies)
            {
                if (colony.Owners.Length == 1)
                {
                    RewindColonyBlocks(colony);
                }
            }

            Task.Run(() =>
            {
                var playerId = player.ID.ToString();

                try
                {
                    using (TrackedPositionContext db = new TrackedPositionContext())
                    {
                        foreach (var trackedPos in db.Positions.Where(p => p.PlayerId == playerId))
                        {
                            var oldest = db.Positions.Where(o => o.X == trackedPos.X && o.Y == trackedPos.Y && o.Z == trackedPos.Z && o.TimeTracked < trackedPos.TimeTracked).OrderBy(tp => tp.TimeTracked).FirstOrDefault();

                            if (oldest == default(TrackedPosition))
                            {
                                oldest = trackedPos;
                            }

                            if (!_queuedPositions.Any(pos => pos.Equals(oldest)))
                            {
                                lock (_queuedPositions)
                                    _queuedPositions.Add(oldest);

                                ChunkQueue.QueuePlayerRequest(oldest.GetVector().ToChunk(), player);
                            }
                        }

                        if (_queuedPositions.Count <= 0)
                        {
                            return;
                        }

                        System.Threading.Thread.Sleep(10000);

                        List <TrackedPosition> replaced = new List <TrackedPosition>();

                        foreach (var trackedPos in _queuedPositions)
                        {
                            if (ServerManager.TryChangeBlock(trackedPos.GetVector(), (ushort)trackedPos.BlockId) == EServerChangeBlockResult.Success)
                            {
                                replaced.Add(trackedPos);
                            }
                        }

                        lock (_queuedPositions)
                        {
                            db.Positions.RemoveRange(_queuedPositions);
                            foreach (var replace in replaced)
                            {
                                _queuedPositions.Remove(replace);
                            }
                        }

                        db.SaveChanges();
                    }
                }
                catch (DbEntityValidationException e)
                {
                    ProcessEntityException(e);
                }
                catch (Exception ex)
                {
                    PandaLogger.LogError(ex);
                }
            });
        }
        public static async void RewindColonyBlocks(Colony colony)
        {
            foreach (var npc in colony.Followers.ToList())
            {
                npc.health = 0;

                if (npc.Job is IAreaJob areaJob)
                {
                    AreaJobTracker.RemoveJob(areaJob);
                }

                npc.ClearJob();
                npc.OnDeath();
            }

            RoamingJobManager.Objectives.Remove(colony);

            ServerManager.ColonyTracker.ColoniesLock.EnterWriteLock();
            ServerManager.ColonyTracker.ColoniesByID.Remove(colony.ColonyID);
            Colony newcolony = new Colony(colony.ColonyID);

            newcolony.Stockpile.AddEnumerable(from unresolved in ServerManager.WorldSettingsReadOnly.InitialStockpile
                                              select new InventoryItem(unresolved.type, unresolved.amount));
            ServerManager.ColonyTracker.ColoniesByID.Add(newcolony.ColonyID, newcolony);
            ServerManager.ColonyTracker.ColoniesLock.ExitWriteLock();
            ServerManager.ColonyTracker.Save();

            await Task.Run(() =>
            {
                try
                {
                    var colonyName = colony.Name;

                    using (TrackedPositionContext db = new TrackedPositionContext())
                    {
                        foreach (var trackedPos in db.Positions.Where(p => p.ColonyId == colonyName))
                        {
                            var oldest = db.Positions.Where(o => o.X == trackedPos.X && o.Y == trackedPos.Y && o.Z == trackedPos.Z && o.TimeTracked < trackedPos.TimeTracked).OrderBy(tp => tp.TimeTracked).FirstOrDefault();

                            if (oldest == default(TrackedPosition))
                            {
                                oldest = trackedPos;
                            }

                            if (!_queuedPositions.Any(pos => pos.Equals(oldest)))
                            {
                                lock (_queuedPositions)
                                    _queuedPositions.Add(oldest);

                                ChunkQueue.QueuePlayerRequest(oldest.GetVector().ToChunk(), colony.Owners.FirstOrDefault());
                            }
                        }

                        if (_queuedPositions.Count <= 0)
                        {
                            return;
                        }

                        System.Threading.Thread.Sleep(10000);

                        List <TrackedPosition> replaced = new List <TrackedPosition>();

                        foreach (var trackedPos in _queuedPositions)
                        {
                            if (ServerManager.TryChangeBlock(trackedPos.GetVector(), (ushort)trackedPos.BlockId) == EServerChangeBlockResult.Success)
                            {
                                replaced.Add(trackedPos);
                            }
                        }

                        lock (_queuedPositions)
                        {
                            db.Positions.RemoveRange(_queuedPositions);
                            foreach (var replace in replaced)
                            {
                                _queuedPositions.Remove(replace);
                            }
                        }

                        db.SaveChanges();
                    }
                }
                catch (DbEntityValidationException e)
                {
                    ProcessEntityException(e);
                }
                catch (Exception ex)
                {
                    PandaLogger.LogError(ex);
                }
            });
        }