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); } }
public SetupThread() { LoadQueue = new ChunkQueue(); GenerationQueue = new ChunkQueue(); VegetationQueue = new ChunkQueue(); UnloadQueue = new ChunkQueue(); }
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); }
/// <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; }
/// <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); } }
/// <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++; }
/// <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); } } }
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 } } }
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( "======================" ); }
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; } }
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; } }
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); } }); }