private void ReceivedMessageTcpBytes(PacketHeader header, ConnectionTcp connection, byte[] message) { HandledTask task = new HandledTask(() => { _Clients[connection].ProcessCompressedMessage(ref message); }); task.Start(); }
/// <summary> /// Runs any postprocessing that is needed after server loads new areas. /// </summary> /// <param name="loadRequest">Load request instance</param> /// <param name="areas">New areas</param> /// <param name="segments">New segments</param> protected override void OnAreasLoaded(LoadRequest loadRequest, List<ServerArea> areas, List<ServerSegment> segments) { if (loadRequest.MessageId < 0 || loadRequest.Entity == null) { return; } // the newly loaded areas/segments aren't usable as they could have been // covered by other players' terrain areas.Clear(); segments.Clear(); // construct player's area keys List<int> areaKeys = new List<int>(); foreach (Tuple<int, int> column in GetEntityColumns(loadRequest.ColumnX, loadRequest.ColumnZ)) { for (int y = 0; y < 256; y += 64) { areaKeys.Add(Area.GenerateKey(column.Item1, y, column.Item2)); } } // retrieve player connection Connection connection = ServerManager.Instance.GetPlayerConnection(loadRequest.Entity.ID); if (connection == null) { // no longer online return; } // process terrain response in a synced and handled task HandledTask task = new HandledTask(() => { // compare the new keys with current ones List<int> currentKeys = new List<int>(); lock (_ClientLock) { currentKeys = _ClientAreas[loadRequest.Entity.ID]; } lock (CollectionsLock) { foreach (int key in areaKeys.Where(a => !currentKeys.Contains(a))) { areas.Add(Areas[key]); } } lock (_ClientLock) { _ClientAreas[loadRequest.Entity.ID] = areaKeys; } if (areas.Count == 0) { // there is actually nothing to send ServerManager.Instance.ServerToClientProvider.TerrainDataResponse(connection, loadRequest.MessageId, new List<ServerArea>(), (byte)0, (byte)0); } else { // send the terrain data to the requesting client int batchSize = Configuration.Network.MaxTerrainBatchSize; byte current = 1; byte total = (byte)Math.Ceiling((float)areas.Count / (float)batchSize); for (int i = 0; i < areas.Count; i += batchSize) { List<ServerArea> partial = areas.Skip(i).Take(batchSize).ToList(); ServerManager.Instance.ServerToClientProvider.TerrainDataResponse(connection, loadRequest.MessageId, partial, current, total); current++; } } }); task.Start(); }