static void LoadChunksBlocking(HashSet <Vector3Int> chunksToLoad)
 {
     try {
         currentlyUsedChunksLock.EnterWriteLock();
         currentlyUsedChunks = new HashSet <Vector3Int> (chunksToLoad);
     } finally {
         if (currentlyUsedChunksLock.IsWriteLockHeld)
         {
             currentlyUsedChunksLock.ExitWriteLock();
         }
     }
     foreach (Vector3Int chunkPosition in chunksToLoad)
     {
         ChunkQueue.QueuePlayerSurrounding(chunkPosition);
     }
     ChunkQueue.PokeThread();
     while (chunksToLoad.Count > 0)
     {
         chunksToLoad.RemoveWhere(chunkPosition => {
             Chunk chunk = World.GetChunk(chunkPosition);
             return(chunk != null && chunk.DataState == Chunk.ChunkDataState.DataFull);
         });
         Thread.Sleep(10);
     }
 }
示例#2
0
 public SetupThread()
 {
     LoadQueue       = new ChunkQueue();
     GenerationQueue = new ChunkQueue();
     VegetationQueue = new ChunkQueue();
     UnloadQueue     = new ChunkQueue();
 }
示例#3
0
 public GZipContext(IGZipStrategy gZipStrategy, string inputFile, string outputFile)
 {
     _gZipStrategy  = gZipStrategy;
     _threadManager = new ThreadManager();
     _inputFile     = inputFile;
     _outputFile    = outputFile;
     _queueReader   = new ChunkQueue(Config.QueueMaxSize);
     _queueWriter   = new ChunkQueue(Config.QueueMaxSize);
 }
示例#4
0
        /// <summary>
        /// <see cref="IGZipStrategy.Read"/>
        /// </summary>
        public void Read(FileStream inputStream, ChunkQueue queueReader)
        {
            var diff      = inputStream.Length - inputStream.Position;
            var bytesRead = diff <= Config.ChunkSize ? (int)diff : Config.ChunkSize;

            var lastBuffer = new byte[bytesRead];

            inputStream.Read(lastBuffer, 0, bytesRead);
            queueReader.Enqueue(lastBuffer);
        }
 void QueueChunk(int cx, int cy, int cz, ChunkQueue queue)
 {
     if (cx >= 0 && cy >= 0 && cz >= 0 && cx < chunksX && cy < chunksY && cz < chunksZ)
     {
         ChunkInfo info = unsortedChunks[cx + chunksX * (cy + cz * chunksY)];
         if (!info.Visited)
         {
             queue.Enqueue(info);
         }
         info.Visited = true;
     }
 }
        void SimpleOcclusionCulling()           // TODO: still broken
        {
            Vector3  p      = game.LocalPlayer.EyePosition;
            Vector3I mapLoc = Vector3I.Floor(p);

            Utils.Clamp(ref mapLoc.X, 0, game.World.Width - 1);
            Utils.Clamp(ref mapLoc.Y, 0, game.World.Height - 1);
            Utils.Clamp(ref mapLoc.Z, 0, game.World.Length - 1);

            int cx = mapLoc.X >> 4;
            int cy = mapLoc.Y >> 4;
            int cz = mapLoc.Z >> 4;

            ChunkInfo chunkIn = unsortedChunks[cx + chunksX * (cy + cz * chunksY)];
            byte      chunkInOcclusionFlags = chunkIn.OcclusionFlags;

            chunkIn.OcclusionFlags = 0;
            ChunkQueue queue = new ChunkQueue(chunksX * chunksY * chunksZ);

            for (int i = 0; i < chunks.Length; i++)
            {
                ChunkInfo chunk = chunks[i];
                chunk.Visited       = false;
                chunk.Occluded      = false;
                chunk.OccludedFlags = chunk.OcclusionFlags;
                chunk.DistanceFlags = 0;
            }

            chunkIn.Visited = true;
            mapLoc          = Vector3I.Floor(p);
            if (game.World.IsValidPos(mapLoc))
            {
                chunkIn.DistanceFlags = flagX | flagY | flagZ;
            }
            else
            {
                chunkIn.OccludedFlags  = chunkIn.OcclusionFlags = chunkInOcclusionFlags;
                chunkIn.DistanceFlags |= (mapLoc.X < 0 || mapLoc.X >= game.World.Width) ? flagX : (byte)0;
                chunkIn.DistanceFlags |= (mapLoc.Y < 0 || mapLoc.Y >= game.World.Height) ? flagY : (byte)0;
                chunkIn.DistanceFlags |= (mapLoc.Z < 0 || mapLoc.Z >= game.World.Length) ? flagZ : (byte)0;
            }

            Console.WriteLine("SRC    {0}", cx + "," + cy + "," + cz);
            QueueChunk(cx - 1, cy, cz, queue);
            QueueChunk(cx + 1, cy, cz, queue);
            QueueChunk(cx, cy - 1, cz, queue);
            QueueChunk(cx, cy + 1, cz, queue);
            QueueChunk(cx, cy, cz - 1, queue);
            QueueChunk(cx, cy, cz + 1, queue);
            ProcessQueue(queue);
            chunkIn.OcclusionFlags = chunkInOcclusionFlags;
        }
示例#7
0
        /// <summary>
        /// <see cref="IGZipStrategy.Handle"/>
        /// </summary>
        public void Handle(KeyValuePair <int, byte[]> chunk, ChunkQueue queueWriter)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (GZipStream cs = new GZipStream(memoryStream, CompressionMode.Compress))
                {
                    cs.Write(chunk.Value, 0, chunk.Value.Length);
                    cs.Flush();
                }

                byte[] compresData = memoryStream.ToArray();
                var    _out        = new KeyValuePair <int, byte[]>(chunk.Key, compresData);
                queueWriter.Enqueue(_out);
            }
        }
示例#8
0
        /// <summary>
        /// <see cref="IGZipStrategy.Read"/>
        /// </summary>
        public void Read(FileStream inputStream, ChunkQueue queueReader)
        {
            var bufLenght = new byte[8];

            inputStream.Read(bufLenght, 0, bufLenght.Length);
            var chunkLenght = BitConverter.ToInt32(bufLenght, 4);

            byte[] compresData = new byte[chunkLenght];
            bufLenght.CopyTo(compresData, 0);
            inputStream.Read(compresData, 8, chunkLenght - 8);

            var chunk = new KeyValuePair <int, byte[]>(counter, compresData);

            queueReader.Enqueue(chunk);
            counter++;
        }
示例#9
0
        /// <summary>
        /// <see cref="IGZipStrategy.Handle"/>
        /// </summary>
        public void Handle(KeyValuePair <int, byte[]> chunk, ChunkQueue queueWriter)
        {
            var dataSize   = BitConverter.ToInt32(chunk.Value, chunk.Value.Length - 4);
            var lastBuffer = new byte[dataSize];

            using (MemoryStream ms = new MemoryStream(chunk.Value))
            {
                using (GZipStream _gz = new GZipStream(ms, CompressionMode.Decompress))
                {
                    var keyVal = new KeyValuePair <int, byte[]>(chunk.Key, lastBuffer);
                    _gz.Read(keyVal.Value, 0, keyVal.Value.Length);
                    var decompressedData = keyVal.Value.ToArray();
                    var chunkDec         = new KeyValuePair <int, byte[]>(keyVal.Key, decompressedData);
                    queueWriter.Enqueue(chunkDec);
                }
            }
        }
示例#10
0
        public TrainTransport(TransportSave transportSave)
        {
            if (transportSave.type == _trackCalculationType.name)
            {
                Position                  = transportSave.position;
                _prevPosition             = transportSave.prevPos;
                _trainId                  = transportSave.itemName;
                TrackPosition             = transportSave.trackPos;
                TrainType                 = Train.TrainTypes[transportSave.itemName];
                _animatedObject           = Train.TrainAnimations[transportSave.itemName];
                _meshedVehicleDescription = new MeshedVehicleDescription(new ClientMeshedObject(_animatedObject.ObjType, new MeshedObjectID(transportSave.meshid)), TrainType.TrainConfiguration.playerSeatOffset, TrainType.TrainConfiguration.AllowPlayerToEditBlocksWhileRiding);
                _idealHeightFromTrack     = TrainType.TrainConfiguration.IdealHeightFromTrack;
                _energy          = transportSave.energy;
                Delay            = TrainType.TrainConfiguration.MoveTimePerBlockMs;
                ManaCostPerBlock = TrainType.TrainConfiguration.EnergyCostPerBlock;
                ChunkQueue.QueueBannerBox(TrackPosition.Add(-30, -30, -30).ToChunk(), TrackPosition.Add(30, 30, 30).ToChunk());

                if (!string.IsNullOrEmpty(transportSave.player))
                {
                    _player = Players.GetPlayer(NetworkID.Parse(transportSave.player));
                    MeshedObjectManager.Attach(_player, _meshedVehicleDescription);
                }
            }
        }
        void ProcessQueue(ChunkQueue queue)
        {
            Vector3I p = chunkPos;

            while (queue.Size > 0)
            {
                ChunkInfo chunk = queue.Dequeue();
                int       x1 = chunk.CentreX - 8, x2 = chunk.CentreX + 8;
                int       y1 = chunk.CentreY - 8, y2 = chunk.CentreY + 8;
                int       z1 = chunk.CentreZ - 8, z2 = chunk.CentreZ + 8;

                int xOffset, yOffset, zOffset;
                int dx = Math.Max(x1 - p.X, Math.Max(0, p.X - x2));
                int dy = Math.Max(y1 - p.Y, Math.Max(0, p.Y - y2));
                int dz = Math.Max(z1 - p.Z, Math.Max(0, p.Z - z2));
                int distX, distY, distZ;

                // X axis collisions
                int dxLeft = Math.Abs(x1 - p.X), dxRight = Math.Abs(x2 - p.X);
                if (dxLeft < dxRight)
                {
                    distX = dxLeft * dxLeft + dy * dy + dz * dz; xOffset = -1;
                }
                else
                {
                    distX = dxRight * dxRight + dy * dy + dz * dz; xOffset = 1;
                }

                // Z axis collisions
                int dxFront = Math.Abs(z1 - p.Z), dxBack = Math.Abs(z2 - p.Z);
                if (dxFront < dxBack)
                {
                    distZ = dx * dx + dy * dy + dxFront * dxFront; zOffset = -1;
                }
                else
                {
                    distZ = dx * dx + dy * dy + dxBack * dxBack; zOffset = 1;
                }

                // Y axis collisions
                int dxBottom = Math.Abs(y1 - p.Y), dxTop = Math.Abs(y2 - p.Y);
                if (dxBottom < dxTop)
                {
                    distY = dx * dx + dxBottom * dxBottom + dz * dz; yOffset = -1;
                }
                else
                {
                    distY = dx * dx + dxTop * dxTop + dz * dz; yOffset = 1;
                }

                chunk.Occluded = true;
                int distMin = Math.Min(distX, Math.Min(distY, distZ));
                int cx = chunk.CentreX >> 4, cy = chunk.CentreY >> 4, cz = chunk.CentreZ >> 4;

                if (!chunk.Empty)
                {
                    Console.WriteLine(chunk.OccludedFlags + " , " + xOffset + " : " + yOffset + " : " + zOffset);
                }
                if (distMin == distX)
                {
                    OccludeX(cx, cy, cz, xOffset, chunk);
                }
                if (distMin == distY)
                {
                    OccludeY(cx, cy, cz, yOffset, chunk);
                }
                if (distMin == distZ)
                {
                    OccludeZ(cx, cy, cz, zOffset, chunk);
                }

                //Console.WriteLine(distMin + " , " + distX + " , " + distY + " , " + distZ);
                //Console.WriteLine(chunk.DistanceFlags + " : " + chunk.OccludedFlags + " : " + chunk.OcclusionFlags);
                QueueChunk(cx - 1, cy, cz, queue);
                QueueChunk(cx + 1, cy, cz, queue);
                QueueChunk(cx, cy, cz - 1, queue);
                QueueChunk(cx, cy, cz + 1, queue);
                QueueChunk(cx, cy - 1, cz, queue);
                QueueChunk(cx, cy + 1, cz, queue);
                if (!chunk.Empty)
                {
                    Console.WriteLine("{0}     D {1}: V {2}, O {3}, {4}", cx + "," + cy + "," + cz, chunk.DistanceFlags,
                                      chunk.OccludedFlags, chunk.OcclusionFlags, chunk.Occluded);
                    Console.WriteLine("    M {0} : X {1}, Y {2}, Z {3} ({4}, {5})", distMin, distX, distY, distZ, dxFront, dxBack);
                }
            }
            Console.WriteLine("======================");
        }
        public void Run()
        {
            LoadQueue       = new ChunkQueue();
            GenerationQueue = new ChunkQueue();
            VegetationQueue = new ChunkQueue();
            BuildQueue      = new ChunkQueue();
            SetupQueue      = new ChunkQueue();
            UnloadQueue     = new ChunkQueue();

            Chunk currentChunk;

            while (true)
            {
                if (!Variables.Game.IsInitialized)
                {
                    continue;
                }

                if (UnloadQueue.Count > 0)
                {
                    currentChunk = UnloadQueue.Dequeue();

                    if (currentChunk == null)
                    {
                        continue;
                    }

                    // Unload Chunk
                    if (Constants.World.SaveDynamicWorld)
                    {
                        ChunkManager.StoreChunkImmediate(currentChunk);
                    }
                    else
                    {
                        currentChunk = null;
                    }
                    Console.Write("UnloadQueue: " + GenerationQueue.Count);

                    // End Unload Chunk

                    LoadQueue.Remove(currentChunk);
                    GenerationQueue.Remove(currentChunk);
                    SetupQueue.Remove(currentChunk);
                }
                else if (LoadQueue.Count > 0)
                {
                    currentChunk = LoadQueue.Dequeue();

                    if (currentChunk == null)
                    {
                        continue;
                    }

                    // Load Chunk

                    ChunkManager.LoadChunkImmediate(currentChunk);
                    currentChunk.BuildOctree();
                    currentChunk.HasData = true;

                    Console.Write("LoadQueue: " + GenerationQueue.Count);

                    // End Load Chunk

                    if (SetupQueue.Contains(currentChunk))
                    {
                        SetupQueue.Remove(currentChunk);
                        SetupQueue.Enqueue(currentChunk);
                    }
                    else
                    {
                        SetupQueue.Enqueue(currentChunk);
                    }
                }
                else if (GenerationQueue.Count > 0)
                {
                    currentChunk = GenerationQueue.Dequeue();

                    if (currentChunk == null)
                    {
                        continue;
                    }

                    // Generate Chunk

                    LandscapeGenerator.SetChunkTerrain(currentChunk);

                    Console.Write("GenerationQueue: " + GenerationQueue.Count);

                    // End Generate Chunk

                    if (VegetationQueue.Contains(currentChunk))
                    {
                        VegetationQueue.Remove(currentChunk);
                        VegetationQueue.Enqueue(currentChunk);
                    }
                    else
                    {
                        AddToVegetation(currentChunk);
                    }
                }
                else if (VegetationQueue.Count > 0)
                {
                    currentChunk = VegetationQueue.Dequeue();

                    if (currentChunk == null)
                    {
                        continue;
                    }

                    // Vegetate Chunk

                    Vegetation.Vegetate(currentChunk);

                    Console.Write("VegetationQueue: " + VegetationQueue.Count);

                    // End Vegetate Chunk

                    if (BuildQueue.Contains(currentChunk))
                    {
                        BuildQueue.Remove(currentChunk);
                        BuildQueue.Enqueue(currentChunk);
                    }
                    else
                    {
                        AddToBuild(currentChunk);
                    }

                    if (VegetationQueue.Count == 0 && !Constants.Engine_Physics.Player.IsReleased)
                    {
                        Constants.Engine_Physics.Player.Release();
                    }
                }
                else if (BuildQueue.Count > 0)
                {
                    currentChunk = BuildQueue.Dequeue();

                    if (currentChunk == null)
                    {
                        continue;
                    }

                    // Build Chunk

                    currentChunk.BuildOctree();
                    currentChunk.HasData = true;

                    Console.Write("BuildQueue: " + BuildQueue.Count);

                    // End Build Chunk

                    if (SetupQueue.Contains(currentChunk))
                    {
                        SetupQueue.Remove(currentChunk);
                        SetupQueue.Enqueue(currentChunk);
                    }
                    else
                    {
                        AddToSetup(currentChunk);
                    }
                }
                else if (SetupQueue.Count > 0)
                {
                    currentChunk = SetupQueue.Dequeue();

                    if (currentChunk == null)
                    {
                        continue;
                    }
                    currentChunk.SetupState = 4;

                    // Setup Chunk

                    currentChunk.BuildGeometry(false);
                    currentChunk.SetupState = 1;

                    Console.Write("SetupQueue: " + SetupQueue.Count);
                    // End Setup Chunk
                }
            }
        }
示例#13
0
        public TransportManager.ETransportUpdateResult Update()
        {
            if (_removed)
            {
                return(TransportManager.ETransportUpdateResult.Remove);
            }

            var currentPositionInt = new Pipliz.Vector3Int(Position);
            var heightFromTrack    = _idealHeightFromTrack;

            if (TrackPosition == Pipliz.Vector3Int.zero)
            {
                for (int i = -1; i > _idealHeightFromTrack * -1; i--)
                {
                    var trackPos = currentPositionInt.Add(0, i, 0);
                    if (World.TryGetTypeAt(trackPos, out ItemTypes.ItemType possibleTrack) &&
                        ConnectedBlockSystem.BlockLookup.TryGetValue(possibleTrack.Name, out var track) &&
                        track.ConnectedBlock.CalculationType == _trackCalculationType.name &&
                        TrainType.ConnectedBlock.BlockType == track.ConnectedBlock.BlockType)
                    {
                        heightFromTrack = i * -1;
                        TrackPosition   = trackPos;
                        break;
                    }
                }
            }

            if (heightFromTrack != _idealHeightFromTrack)
            {
                Position = currentPositionInt.Add(0, heightFromTrack, 0).Vector;
                _meshedVehicleDescription.Object.SendMoveToInterpolated(Position, Quaternion.identity, (float)GetDelayMillisecondsToNextUpdate() / 1000f, _animatedObject.ObjSettings);
            }
            else if (TrackPosition != Pipliz.Vector3Int.zero)
            {
                bool    moved        = false;
                ICSType trainStation = null;

                if (_trainMoveTime < TimeCycle.TotalHours)
                {
                    if (_minStopNextTime < TimeCycle.TotalHours)
                    {
                        foreach (var stationSide in _trackCalculationType.AvailableBlockSides)
                        {
                            var stationCheck = TrackPosition.GetBlockOffset(stationSide);

                            if (World.TryGetTypeAt(stationCheck, out ItemTypes.ItemType possibleStation) &&
                                ItemCache.CSItems.TryGetValue(possibleStation.Name, out var station) &&
                                station.TrainStationSettings != null &&
                                station.TrainStationSettings.BlockType == TrainType.ConnectedBlock.BlockType)
                            {
                                trainStation = station;

                                foreach (var kvp in RoamingJobManager.Objectives.Values)
                                {
                                    if (kvp.TryGetValue(trainStation.TrainStationSettings.ObjectiveCategory, out var locDic) &&
                                        locDic.TryGetValue(stationCheck, out var roamingJobState))
                                    {
                                        var manaNeeded = RoamingJobState.GetActionsMaxEnergy(TrainType.TrainConfiguration.EnergyActionEnergyName, roamingJobState.Colony, TrainType.TrainConfiguration.RoamingJobCategory) - _energy;

                                        var  existing = roamingJobState.GetActionEnergy(TrainType.TrainConfiguration.EnergyActionEnergyName);
                                        bool isWorked = true;

                                        try
                                        {
                                            if (roamingJobState.Colony.JobFinder.JobsData != null)
                                            {
                                                foreach (var job in roamingJobState.Colony.JobFinder.JobsData.OpenJobs)
                                                {
                                                    try
                                                    {
                                                        if (job != null && job.GetJobLocation() == stationCheck)
                                                        {
                                                            isWorked = false;
                                                            break;
                                                        }
                                                    }
                                                    catch { }
                                                }
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            if (roamingJobState.Colony.JobFinder == null)
                                            {
                                                APILogger.Log("roamingJobState.Colony.JobFinder == null");
                                            }

                                            if (roamingJobState.Colony.JobFinder.JobsData == null)
                                            {
                                                APILogger.Log("roamingJobState.Colony.JobFinder.JobsData == null");
                                            }

                                            if (roamingJobState.Colony.JobFinder.JobsData.OpenJobs == null)
                                            {
                                                APILogger.Log("roamingJobState.Colony.JobFinder.JobsData.OpenJobs == null");
                                            }

                                            APILogger.LogError(ex);
                                        }

                                        if (!isWorked)
                                        {
                                            Indicator.SendIconIndicatorNear(stationCheck.Add(0, 1, 0).Vector, new IndicatorState(10, "npcicon", true, false));
                                        }
                                        else if (existing > 0)
                                        {
                                            if (existing >= manaNeeded)
                                            {
                                                roamingJobState.SubtractFromActionEnergy(TrainType.TrainConfiguration.EnergyActionEnergyName, manaNeeded);
                                                _energy = RoamingJobState.GetActionsMaxEnergy(TrainType.TrainConfiguration.EnergyActionEnergyName, roamingJobState.Colony, TrainType.TrainConfiguration.RoamingJobCategory);
                                                roamingJobState.SubtractFromActionEnergy(TrainType.TrainConfiguration.DurabilityActionEnergyName, .01f);
                                            }
                                            else
                                            {
                                                roamingJobState.SubtractFromActionEnergy(TrainType.TrainConfiguration.EnergyActionEnergyName, existing);
                                                _energy += existing;
                                                roamingJobState.SubtractFromActionEnergy(TrainType.TrainConfiguration.DurabilityActionEnergyName, .01f);
                                            }

                                            Indicator.SendIconIndicatorNear(stationCheck.Add(0, 1, 0).Vector, new IndicatorState(10, TrainType.TrainConfiguration.EnergyType));
                                            _minStopNextTime = TimeCycle.TotalHours + 2;
                                            _trainMoveTime   = TimeCycle.TotalHours + 1;
                                            existing         = roamingJobState.GetActionEnergy(TrainType.TrainConfiguration.EnergyActionEnergyName);
                                        }
                                        else
                                        {
                                            Indicator.SendIconIndicatorNear(stationCheck.Add(0, 1, 0).Vector, new IndicatorState(10, TrainType.TrainConfiguration.EnergyType, true, false));
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    if (trainStation == null && _energy > 0)
                    {
                        foreach (var side in _trackCalculationType.AvailableBlockSides)
                        {
                            var searchSide = TrackPosition.GetBlockOffset(side);
                            var proposePos = currentPositionInt.GetBlockOffset(side).Vector;

                            if (World.TryGetTypeAt(searchSide, out ItemTypes.ItemType possibleTrack) &&
                                ConnectedBlockSystem.BlockLookup.TryGetValue(possibleTrack.Name, out var track) &&
                                track.ConnectedBlock.CalculationType == _trackCalculationType.name &&
                                TrainType.ConnectedBlock.BlockType == track.ConnectedBlock.BlockType &&
                                proposePos != _prevPosition)
                            {
                                _prevPosition = Position;
                                TrackPosition = searchSide;
                                Position      = currentPositionInt.GetBlockOffset(side).Vector;
                                _meshedVehicleDescription.Object.SendMoveToInterpolated(Position, Quaternion.identity, (float)GetDelayMillisecondsToNextUpdate() / 1000f, _animatedObject.ObjSettings);
                                _energy -= ManaCostPerBlock;

                                if (_energy < 0)
                                {
                                    _energy = 0;
                                }

                                ChunkQueue.QueueBannerBox(TrackPosition.Add(-30, -30, -30).ToChunk(), TrackPosition.Add(30, 30, 30).ToChunk());

                                moved = true;
                                break;
                            }
                        }
                    }
                }

                if (!moved)
                {
                    _meshedVehicleDescription.Object.SendMoveToInterpolated(Position, Quaternion.identity, (float)GetDelayMillisecondsToNextUpdate() / 1000f, _animatedObject.ObjSettings);
                }

                if (!moved && _energy > 0)
                {
                    _prevPosition = Vector3.zero;
                }

                if (!moved && _energy <= 0)
                {
                    _trainMoveTime = 0;
                    Indicator.SendIconIndicatorNear(new Pipliz.Vector3Int(Position).Add(0, 2, 0).Vector, new IndicatorState((float)GetDelayMillisecondsToNextUpdate() / 1000f, TrainType.TrainConfiguration.EnergyType, true, false));
                }
            }

            return(TransportManager.ETransportUpdateResult.KeepUpdating);
        }
        void SimpleOcclusionCulling()
        {
            // TODO: broken
            Vector3 p = game.LocalPlayer.EyePosition;
            Vector3I chunkLoc = Vector3I.Floor( p );
            Utils.Clamp( ref chunkLoc.X, 0, game.Map.Width - 1 );
            Utils.Clamp( ref chunkLoc.Y, 0, game.Map.Height - 1 );
            Utils.Clamp( ref chunkLoc.Z, 0, game.Map.Length- 1 );

            int cx = chunkLoc.X >> 4;
            int cy = chunkLoc.Y >> 4;
            int cz = chunkLoc.Z >> 4;

            ChunkInfo chunkIn = unsortedChunks[cx + chunksX * (cy + cz * chunksY)];
            byte chunkInFlags = chunkIn.OcclusionFlags;
            chunkIn.OcclusionFlags = 0;

            ChunkQueue queue = new ChunkQueue( chunksX * chunksY * chunksZ );
            for( int i = 0; i < chunks.Length; i++ ) {
                chunks[i].Visited = false;
                chunks[i].Occluded = false;
                chunks[i].VisibilityFlags = 0;
            }

            chunkIn.Visited = true;
            QueueChunk( cx - 1, cy, cz, queue );
            QueueChunk( cx + 1, cy, cz, queue );
            QueueChunk( cx, cy - 1, cz, queue );
            QueueChunk( cx, cy + 1, cz, queue );
            QueueChunk( cx, cy, cz - 1, queue );
            QueueChunk( cx, cy, cz + 1, queue );

            ProcessQueue( chunkIn, queue );
            chunkIn.OcclusionFlags = chunkInFlags;
        }
        void SimpleOcclusionCulling()
        {
            // TODO: still broken
            Vector3 p = game.LocalPlayer.EyePosition;
            Vector3I mapLoc = Vector3I.Floor( p );
            Utils.Clamp( ref mapLoc.X, 0, game.Map.Width - 1 );
            Utils.Clamp( ref mapLoc.Y, 0, game.Map.Height - 1 );
            Utils.Clamp( ref mapLoc.Z, 0, game.Map.Length- 1 );

            int cx = mapLoc.X >> 4;
            int cy = mapLoc.Y >> 4;
            int cz = mapLoc.Z >> 4;

            ChunkInfo chunkIn = unsortedChunks[cx + chunksX * (cy + cz * chunksY)];
            byte chunkInOcclusionFlags = chunkIn.OcclusionFlags;
            chunkIn.OcclusionFlags = 0;
            ChunkQueue queue = new ChunkQueue( chunksX * chunksY * chunksZ );
            for( int i = 0; i < chunks.Length; i++ ) {
                ChunkInfo chunk = chunks[i];
                chunk.Visited = false;
                chunk.Occluded = false;
                chunk.OccludedFlags = chunk.OcclusionFlags;
                chunk.DistanceFlags = 0;
            }

            chunkIn.Visited = true;
            mapLoc = Vector3I.Floor( p );
            if( game.Map.IsValidPos( mapLoc ) ) {
                chunkIn.DistanceFlags = flagX | flagY | flagZ;
            } else {
                chunkIn.OccludedFlags = chunkIn.OcclusionFlags = chunkInOcclusionFlags;
                chunkIn.DistanceFlags |= (mapLoc.X < 0 || mapLoc.X >= game.Map.Width) ? flagX : (byte)0;
                chunkIn.DistanceFlags |= (mapLoc.Y < 0 || mapLoc.Y >= game.Map.Height) ? flagY : (byte)0;
                chunkIn.DistanceFlags |= (mapLoc.Z < 0 || mapLoc.Z >= game.Map.Length) ? flagZ : (byte)0;
            }

            Console.WriteLine( "SRC    {0}", cx + "," + cy + "," + cz );
            QueueChunk( cx - 1, cy, cz, queue );
            QueueChunk( cx + 1, cy, cz, queue );
            QueueChunk( cx, cy - 1, cz, queue );
            QueueChunk( cx, cy + 1, cz, queue );
            QueueChunk( cx, cy, cz - 1, queue );
            QueueChunk( cx, cy, cz + 1, queue );
            ProcessQueue( queue );
            chunkIn.OcclusionFlags = chunkInOcclusionFlags;
        }
 void QueueChunk( int cx, int cy, int cz, ChunkQueue queue )
 {
     if( cx >= 0 && cy >= 0 && cz >= 0 && cx < chunksX && cy < chunksY && cz < chunksZ ) {
         ChunkInfo info = unsortedChunks[cx + chunksX * (cy + cz * chunksY)];
         if( !info.Visited )
             queue.Enqueue( info );
         info.Visited = true;
     }
 }
        void ProcessQueue( ChunkQueue queue )
        {
            Vector3I p = chunkPos;
            while( queue.Size > 0 ) {
                ChunkInfo chunk = queue.Dequeue();
                int x1 = chunk.CentreX - 8, x2 = chunk.CentreX + 8;
                int y1 = chunk.CentreY - 8, y2 = chunk.CentreY + 8;
                int z1 = chunk.CentreZ - 8, z2 = chunk.CentreZ + 8;

                int xOffset, yOffset, zOffset;
                int dx = Math.Max( x1 - p.X, Math.Max( 0, p.X - x2 ) );
                int dy = Math.Max( y1 - p.Y, Math.Max( 0, p.Y - y2 ) );
                int dz = Math.Max( z1 - p.Z, Math.Max( 0, p.Z - z2 ) );
                int distX, distY, distZ;

                // X axis collisions
                int dxLeft = Math.Abs( x1 - p.X ), dxRight = Math.Abs( x2 - p.X );
                if( dxLeft < dxRight ) {
                    distX = dxLeft * dxLeft + dy * dy + dz * dz; xOffset = -1;
                } else {
                    distX = dxRight * dxRight + dy * dy + dz * dz; xOffset = 1;
                }

                // Z axis collisions
                int dxFront = Math.Abs( z1 - p.Z ), dxBack = Math.Abs( z2 - p.Z );
                if( dxFront < dxBack ) {
                    distZ = dx * dx + dy * dy + dxFront * dxFront; zOffset = -1;
                } else {
                    distZ = dx * dx + dy * dy + dxBack * dxBack; zOffset = 1;
                }

                // Y axis collisions
                int dxBottom = Math.Abs( y1 - p.Y ), dxTop = Math.Abs( y2 - p.Y );
                if( dxBottom < dxTop ) {
                    distY = dx * dx + dxBottom * dxBottom + dz * dz; yOffset = -1;
                } else {
                    distY = dx * dx + dxTop * dxTop + dz * dz; yOffset = 1;
                }

                chunk.Occluded = true;
                int distMin = Math.Min( distX, Math.Min( distY, distZ ) );
                int cx = chunk.CentreX >> 4, cy = chunk.CentreY >> 4, cz = chunk.CentreZ >> 4;

                if( !chunk.Empty ) {
                    Console.WriteLine( chunk.OccludedFlags + " , " + xOffset + " : " + yOffset + " : " + zOffset );
                }
                if( distMin == distX ) OccludeX( cx, cy, cz, xOffset, chunk );
                if( distMin == distY ) OccludeY( cx, cy, cz, yOffset, chunk );
                if( distMin == distZ ) OccludeZ( cx, cy, cz, zOffset, chunk );

                //Console.WriteLine( distMin + " , " + distX + " , " + distY + " , " + distZ );
                //Console.WriteLine( chunk.DistanceFlags + " : " + chunk.OccludedFlags + " : " + chunk.OcclusionFlags );
                QueueChunk( cx - 1, cy, cz, queue );
                QueueChunk( cx + 1, cy, cz, queue );
                QueueChunk( cx, cy, cz - 1, queue );
                QueueChunk( cx, cy, cz + 1, queue );
                QueueChunk( cx, cy - 1, cz, queue );
                QueueChunk( cx, cy + 1, cz, queue );
                if( !chunk.Empty ) {
                    Console.WriteLine( "{0}     D {1}: V {2}, O {3}, {4}", cx + "," + cy + "," + cz, chunk.DistanceFlags,
                              chunk.OccludedFlags, chunk.OcclusionFlags, chunk.Occluded );
                    Console.WriteLine( "    M {0} : X {1}, Y {2}, Z {3} ({4}, {5})", distMin, distX, distY, distZ, dxFront, dxBack );
                }
            }
            Console.WriteLine( "======================" );
        }
示例#18
0
        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);
                }
            });
        }
        void ProcessQueue( ChunkInfo src, ChunkQueue queue )
        {
            Vector3I p = new Vector3I( src.CentreX, src.CentreY, src.CentreZ );
            while( queue.Size > 0 ) {
                ChunkInfo chunk = queue.Dequeue();
                chunk.VisibilityFlags = chunk.OcclusionFlags;
                int x1 = chunk.CentreX - 8, x2 = chunk.CentreX + 8;
                int y1 = chunk.CentreY - 8, y2 = chunk.CentreY + 8;
                int z1 = chunk.CentreZ - 8, z2 = chunk.CentreZ + 8;
                int cx = chunk.CentreX >> 4;
                int cy = chunk.CentreY >> 4;
                int cz = chunk.CentreZ >> 4;

                int xOffset, yOffset, zOffset;
                int dx = Math.Max( x1 - p.X, Math.Max( 0, p.X - x2 ) );
                int dy = Math.Max( y1 - p.Y, Math.Max( 0, p.Y - y2 ) );
                int dz = Math.Max( z1 - p.Z, Math.Max( 0, p.Z - z2 ) );
                int distX, distY, distZ;

                // X axis collisions
                int dxLeft = Math.Abs( x1 - p.X ), dxRight = Math.Abs( x2 - p.X );
                if( dxLeft < dxRight ) {
                    distX = dxLeft * dxLeft + dy * dy + dz * dz; xOffset = -1;
                } else {
                    distX = dxRight * dxRight + dy * dy + dz * dz; xOffset = 1;
                }

                // Z axis collisions
                int dxFront = Math.Abs( z1 - p.Z ), dxBack = Math.Abs( z2 - p.Z );
                if( dxFront < dxBack ) {
                    distZ = dx * dx + dy * dy + dxFront * dxFront; zOffset = -1;
                } else {
                    distZ = dx * dx + dy * dy + dxBack * dxBack; zOffset = 1;
                }

                // Y axis collisions
                int dxBottom = Math.Abs( y1 - p.Y ), dxTop = Math.Abs( y2 - p.Y );
                if( dxBottom < dxTop ) {
                    distY = dx * dx + dxBottom * dxBottom + dz * dz; yOffset = -1;
                } else {
                    distY = dx * dx + dxTop * dxTop + dz * dz; yOffset = 1;
                }

                int distMin = Math.Min( distX, Math.Min( distY, distZ ) );
                bool occlude = true;
                byte flags = 0;
                if( distMin == distX )
                    OccludeX( cx, cy, cz, xOffset, ref occlude, ref flags );
                if( distMin == distZ )
                    OccludeZ( cx, cy, cz, zOffset, ref occlude, ref flags );
                if( distMin == distY )
                    OccludeY( cx, cy, cz, yOffset, ref occlude, ref flags );

                if( occlude )
                    chunk.Occluded = true;
                chunk.VisibilityFlags = (byte)( flags | chunk.OcclusionFlags );
                QueueChunk( cx - 1, cy, cz, queue );
                QueueChunk( cx + 1, cy, cz, queue );
                QueueChunk( cx, cy, cz - 1, queue );
                QueueChunk( cx, cy, cz + 1, queue );
                QueueChunk( cx, cy - 1, cz, queue );
                QueueChunk( cx, cy + 1, cz, queue );
            }
            Console.WriteLine( "======================" );
        }
        public void DoJob(IIterationType iterationType, IAreaJob areaJob, ConstructionJobInstance job, ref NPCBase.NPCState state)
        {
            int i   = 0;
            var bpi = iterationType as SchematicIterator;

            if (bpi == null)
            {
                SettlersLogger.Log(ChatColor.yellow, "iterationType must be of type SchematicIterator for the SchematicBuilder.");
                state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name));
                AreaJobTracker.RemoveJob(areaJob);
                return;
            }

            while (true) // This is to move past air.
            {
                if (i > 4000)
                {
                    break;
                }

                var adjX      = iterationType.CurrentPosition.x - bpi.BuilderSchematic.StartPos.x;
                var adjY      = iterationType.CurrentPosition.y - bpi.BuilderSchematic.StartPos.y;
                var adjZ      = iterationType.CurrentPosition.z - bpi.BuilderSchematic.StartPos.z;
                var block     = bpi.BuilderSchematic.GetBlock(adjX, adjY, adjZ);
                var mapped    = block.MappedBlock;
                var buildType = ItemTypes.GetType(mapped.CSIndex);

                if (buildType == null)
                {
                    state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name));
                    AreaJobTracker.RemoveJob(areaJob);
                    return;
                }

                if (World.TryGetTypeAt(iterationType.CurrentPosition, out ushort foundTypeIndex))
                {
                    i++;
                    var founditemId = ItemId.GetItemId(foundTypeIndex);

                    if (foundTypeIndex == buildType.ItemIndex || buildType.Name.Contains("bedend") || (founditemId.Name.Contains("bedend") && buildType.ItemIndex == ColonyBuiltIn.ItemTypes.AIR)) // check if the blocks are the same, if they are, move past. Most of the time this will be air.
                    {
                        if (iterationType.MoveNext())
                        {
                            continue;
                        }
                        else
                        {
                            if (_needsChunkLoaded.Contains(bpi))
                            {
                                _needsChunkLoaded.Remove(bpi);
                            }

                            state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name));
                            AreaJobTracker.RemoveJob(areaJob);
                            return;
                        }
                    }

                    Stockpile ownerStockPile = areaJob.Owner.Stockpile;

                    bool stockpileContainsBuildItem = buildType.ItemIndex == ColonyBuiltIn.ItemTypes.AIR.Id;

                    if (!stockpileContainsBuildItem && ownerStockPile.Contains(buildType.ItemIndex))
                    {
                        stockpileContainsBuildItem = true;
                    }

                    if (!stockpileContainsBuildItem && buildType.Name.Contains("bed") && ownerStockPile.Contains(ItemId.GetItemId("bed")))
                    {
                        stockpileContainsBuildItem = true;
                    }

                    if (!stockpileContainsBuildItem &&
                        !string.IsNullOrWhiteSpace(buildType.ParentType) &&
                        ownerStockPile.Contains(buildType.ParentItemType.ItemIndex))
                    {
                        stockpileContainsBuildItem = true;
                    }

                    if (stockpileContainsBuildItem)
                    {
                        if (foundTypeIndex != ColonyBuiltIn.ItemTypes.AIR.Id && foundTypeIndex != ColonyBuiltIn.ItemTypes.WATER.Id)
                        {
                            var foundItem = ItemTypes.GetType(foundTypeIndex);

                            if (foundItem != null && foundItem.ItemIndex != ColonyBuiltIn.ItemTypes.AIR.Id && foundItem.OnRemoveItems != null && foundItem.OnRemoveItems.Count > 0)
                            {
                                ownerStockPile.Add(foundItem.OnRemoveItems.Select(itm => itm.item).ToList());
                            }
                        }

                        var changeResult = ServerManager.TryChangeBlock(iterationType.CurrentPosition, buildType.ItemIndex, new BlockChangeRequestOrigin(job.Owner), ESetBlockFlags.DefaultAudio);

                        if (changeResult == EServerChangeBlockResult.Success)
                        {
                            if (buildType.ItemIndex != ColonyBuiltIn.ItemTypes.AIR.Id)
                            {
                                if (--job.StoredItemCount <= 0)
                                {
                                    job.ShouldTakeItems = true;
                                    state.JobIsDone     = true;
                                }

                                ownerStockPile.TryRemove(buildType.ItemIndex);

                                if (buildType.Name.Contains("bed"))
                                {
                                    ownerStockPile.TryRemove(ItemId.GetItemId("bed"));
                                }
                            }
                        }
                        else if (changeResult != EServerChangeBlockResult.CancelledByCallback)
                        {
                            if (!_needsChunkLoaded.Contains(bpi))
                            {
                                _needsChunkLoaded.Add(bpi);
                            }

                            state.SetIndicator(new Shared.IndicatorState(5f, buildType.Name));
                            ChunkQueue.QueuePlayerSurrounding(iterationType.CurrentPosition.ToChunk());
                            return;
                        }
                    }
                    else
                    {
                        state.SetIndicator(new Shared.IndicatorState(5f, buildType.Name, true, false));
                        return;
                    }
                }
                else
                {
                    if (!_needsChunkLoaded.Contains(bpi))
                    {
                        _needsChunkLoaded.Add(bpi);
                    }

                    ChunkQueue.QueuePlayerSurrounding(iterationType.CurrentPosition.ToChunk());
                    state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name));
                    return;
                }


                if (iterationType.MoveNext())
                {
                    if (buildType.ItemIndex != ColonyBuiltIn.ItemTypes.AIR.Id)
                    {
                        state.SetIndicator(new Shared.IndicatorState(GetCooldown(), buildType.ItemIndex));
                    }
                    else
                    {
                        state.SetIndicator(new Shared.IndicatorState(GetCooldown(), foundTypeIndex));
                    }

                    return;
                }
                else
                {
                    if (_needsChunkLoaded.Contains(bpi))
                    {
                        _needsChunkLoaded.Remove(bpi);
                    }

                    // failed to find next position to do job at, self-destruct
                    state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name));
                    AreaJobTracker.RemoveJob(areaJob);
                    return;
                }
            }

            if (iterationType.MoveNext())
            {
                state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name));
                return;
            }
            else
            {
                if (_needsChunkLoaded.Contains(bpi))
                {
                    _needsChunkLoaded.Remove(bpi);
                }

                // failed to find next position to do job at, self-destruct
                state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name));
                AreaJobTracker.RemoveJob(areaJob);
                SettlersLogger.Log(ChatColor.yellow, "Failed to MoveNext after while. Iterator position: {0}.", iterationType.CurrentPosition);
                return;
            }
        }
示例#21
0
        public void DoJob(IIterationType iterationType, IAreaJob areaJob, ConstructionJobInstance job, ref NPCBase.NPCState state)
        {
            int i   = 0;
            var bpi = iterationType as ArchitectIterator;

            if (bpi == null)
            {
                SettlersLogger.Log(ChatColor.yellow, "iterationType must be of type ArchitectIterator for the ArchitectBuilder.");
                state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name));
                AreaJobTracker.RemoveJob(areaJob);
                return;
            }

            while (true) // move past air
            {
                if (i > 4000)
                {
                    break;
                }

                i++;

                var adjX = iterationType.CurrentPosition.x - bpi.BuilderSchematic.StartPos.x;
                var adjY = iterationType.CurrentPosition.y - bpi.BuilderSchematic.StartPos.y;
                var adjZ = iterationType.CurrentPosition.z - bpi.BuilderSchematic.StartPos.z;
                var prvX = bpi.PreviousPosition.x - bpi.BuilderSchematic.StartPos.x;
                var prvY = bpi.PreviousPosition.y - bpi.BuilderSchematic.StartPos.y;
                var prvZ = bpi.PreviousPosition.z - bpi.BuilderSchematic.StartPos.z;

                if (World.TryGetTypeAt(iterationType.CurrentPosition, out ItemTypes.ItemType foundType))
                {
                    state.SetCooldown(2);
                    state.SetIndicator(new Shared.IndicatorState(2, foundType.Name));

                    if (foundType.ItemIndex == ColonyBuiltIn.ItemTypes.AIR ||
                        foundType.Name == ColonyBuiltIn.ItemTypes.BANNER)
                    {
                        if (!MoveNext(iterationType, areaJob, job, bpi, prvX, prvY, prvZ))
                        {
                            return;
                        }

                        continue;
                    }

                    try
                    {
                        bpi.BuilderSchematic.Blocks[adjX, adjY, adjZ].BlockID = foundType.Name;
                    }
                    catch (IndexOutOfRangeException)
                    {
                        SettlersLogger.Log(ChatColor.red, $"Index out of range on ArchitectBuilder {adjX}, {adjY}, {adjZ} to a max of {bpi.BuilderSchematic.Blocks.GetLength(0)}, {bpi.BuilderSchematic.Blocks.GetLength(1)}, {bpi.BuilderSchematic.Blocks.GetLength(2)}.");

                        CleanupJob(iterationType, areaJob, job, bpi, prvX, prvY, prvZ);
                        break;
                    }

                    if (!foundType.Name.Contains("bedend"))
                    {
                        ServerManager.TryChangeBlock(iterationType.CurrentPosition, SettlersBuiltIn.ItemTypes.SELECTOR.Id, new BlockChangeRequestOrigin(job.Owner), ESetBlockFlags.DefaultAudio);
                    }

                    MoveNext(iterationType, areaJob, job, bpi, prvX, prvY, prvZ);
                }
                else
                {
                    if (!_needsChunkLoaded.Contains(bpi))
                    {
                        _needsChunkLoaded.Add(bpi);
                    }

                    ChunkQueue.QueuePlayerSurrounding(iterationType.CurrentPosition.ToChunk());
                    state.SetIndicator(new Shared.IndicatorState(5f, ColonyBuiltIn.ItemTypes.ERRORIDLE.Name));
                }

                break;
            }
        }
示例#22
0
        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);
                }
            });
        }