public void UpdateChunks(int radius, CancellationToken token, bool sync, bool remove) { int chunkX = (int)(Math.Floor(Position.X)) >> 4; int chunkZ = (int)(Math.Floor(Position.Z)) >> 4; Dictionary<int, int> nearbyChunks = new Dictionary<int, int>(); MapChunkBulkPacket chunkPacket = null; if(sync) chunkPacket = new MapChunkBulkPacket(); for (int x = chunkX - radius; x <= chunkX + radius; ++x) { for (int z = chunkZ - radius; z <= chunkZ + radius; ++z) { if (token.IsCancellationRequested) return; int packedChunk = UniversalCoords.FromChunkToPackedChunk(x, z); nearbyChunks.Add(packedChunk, packedChunk); if (!LoadedChunks.ContainsKey(packedChunk)) { Chunk chunk; if (sync) chunk = World.GetChunkFromChunkSync(x, z, true, true) as Chunk; else chunk = World.GetChunkFromChunkAsync(x, z, Client, true, true) as Chunk; LoadedChunks.TryAdd(packedChunk, chunk); if (chunk == null) continue; if (chunk.LightToRecalculate) { #if PROFILE Stopwatch watch = new Stopwatch(); watch.Start(); chunk.RecalculateSky(); watch.Stop(); World.Logger.Log(LogLevel.Info, "Skylight recalc: {0}", watch.ElapsedMilliseconds); #else chunk.RecalculateSky(); #endif } chunk.AddClient(Client); if(!sync) _client.SendChunk(chunk); else chunkPacket.ChunksToSend.Add(chunk); } } } if(sync) _client.Send_Sync_Packet(chunkPacket); if (remove) { foreach (int c in LoadedChunks.Keys.Where(c => !nearbyChunks.ContainsKey(c))) { if (token.IsCancellationRequested) return; Chunk chunk; LoadedChunks.TryRemove(c, out chunk); if (chunk != null) chunk.RemoveClient(_client); } } }
internal void SendChunks(object state) { MapChunkBulkPacket packet = new MapChunkBulkPacket(); for (int i = 0; i < 20 && !ChunksToBeSent.IsEmpty; ++i) { Chunk chunk; ChunksToBeSent.TryDequeue(out chunk); packet.ChunksToSend.Add(chunk); } SendPacket(packet); if (ChunksToBeSent.IsEmpty) { _chunkSendTimer.Change(Timeout.Infinite, Timeout.Infinite); Interlocked.Exchange(ref _chunkTimerRunning, 0); } if (!ChunksToBeSent.IsEmpty) { int running = Interlocked.Exchange(ref _chunkTimerRunning, 1); if (running == 0) { if (_lastChunkTimerStart != DateTime.MinValue) _startDelay = 1000 - (int)(DateTime.Now - _lastChunkTimerStart).TotalMilliseconds; if (_startDelay < 0) _startDelay = 0; _chunkSendTimer.Change(_startDelay, 1000); } } _lastChunkTimerStart = DateTime.Now; }