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; }
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); } } } }