private byte[] Compress(ICollection <Packet> packets) { long length = 0; foreach (Packet packet in packets) { length += packet.Encode().Length; } var compressionLevel = _session.CompressionThreshold > -1 && length >= _session.CompressionThreshold ? System.IO.Compression.CompressionLevel.Fastest : System.IO.Compression.CompressionLevel.NoCompression; using (MemoryStream stream = MiNetServer.MemoryStreamManager.GetStream()) { int checksum; using (var compressStream = new DeflateStream(stream, compressionLevel, true)) { foreach (Packet packet in packets) { byte[] bs = packet.Encode(); if (bs != null && bs.Length > 0) { BatchUtils.WriteLength(compressStream, bs.Length); compressStream.Write(bs, 0, bs.Length); } packet.PutPool(); } compressStream.Flush(); } byte[] bytes = stream.ToArray(); return(bytes); } }
private void SendQueue() { if (_sendQueueNotConcurrent.Count == 0) { return; } if (!Monitor.TryEnter(_syncHack)) { return; } try { using (MemoryStream memStream = MiNetServer.MemoryStreamManager.GetStream()) { Queue <Package> queue = _sendQueueNotConcurrent; int messageCount = 0; int lenght = queue.Count; for (int i = 0; i < lenght; i++) { Package package = null; lock (_queueSync) { if (queue.Count == 0) { break; } try { package = queue.Dequeue(); } catch (Exception e) { } } if (package == null) { continue; } if (State == ConnectionState.Unconnected) { package.PutPool(); continue; } if (lenght == 1) { Server.SendPackage(this, package); } else if (package is McpeWrapper) { SendBuffered(messageCount, memStream); messageCount = 0; Server.SendPackage(this, package); Thread.Sleep(1); // Really important to slow down speed a bit } else if (package.NoBatch) { SendBuffered(messageCount, memStream); messageCount = 0; Server.SendPackage(this, package); } else { if (messageCount == 0) { memStream.Position = 0; memStream.SetLength(0); } byte[] bytes = package.Encode(); if (bytes != null) { messageCount++; BatchUtils.WriteLength(memStream, bytes.Length); //memStream.Write(BitConverter.GetBytes(Endian.SwapInt32(bytes.Length)), 0, 4); memStream.Write(bytes, 0, bytes.Length); } package.PutPool(); } } if (State == ConnectionState.Unconnected) { return; } SendBuffered(messageCount, memStream); } } finally { Monitor.Exit(_syncHack); } }
protected virtual void BroadCastMovement(Player[] players, Entity[] entities) { DateTime now = DateTime.UtcNow; if (players.Length == 0) { return; } if (players.Length <= 1 && entities.Length == 0) { return; } if (now - _lastBroadcast < TimeSpan.FromMilliseconds(50)) { return; } DateTime tickTime = _lastSendTime; _lastSendTime = DateTime.UtcNow; using (MemoryStream stream = MiNetServer.MemoryStreamManager.GetStream()) { int playerMoveCount = 0; int entiyMoveCount = 0; foreach (var player in players) { if (now - player.LastUpdatedTime <= now - tickTime) { PlayerLocation knownPosition = player.KnownPosition; McpeMovePlayer move = McpeMovePlayer.CreateObject(); move.entityId = player.EntityId; move.x = knownPosition.X; move.y = knownPosition.Y + 1.62f; move.z = knownPosition.Z; move.yaw = knownPosition.Yaw; move.pitch = knownPosition.Pitch; move.headYaw = knownPosition.HeadYaw; move.mode = 0; byte[] bytes = move.Encode(); BatchUtils.WriteLength(stream, bytes.Length); stream.Write(bytes, 0, bytes.Length); move.PutPool(); playerMoveCount++; } } foreach (var entity in entities) { if (now - entity.LastUpdatedTime <= now - tickTime) { { McpeMoveEntity moveEntity = McpeMoveEntity.CreateObject(); moveEntity.entityId = entity.EntityId; moveEntity.position = (PlayerLocation)entity.KnownPosition.Clone(); moveEntity.position.Y += entity.PositionOffset; byte[] bytes = moveEntity.Encode(); BatchUtils.WriteLength(stream, bytes.Length); stream.Write(bytes, 0, bytes.Length); moveEntity.PutPool(); } { McpeSetEntityMotion entityMotion = McpeSetEntityMotion.CreateObject(); entityMotion.entityId = entity.EntityId; entityMotion.velocity = entity.Velocity; byte[] bytes = entityMotion.Encode(); BatchUtils.WriteLength(stream, bytes.Length); stream.Write(bytes, 0, bytes.Length); entityMotion.PutPool(); } entiyMoveCount++; } } if (playerMoveCount == 0 && entiyMoveCount == 0) { return; } if (players.Length == 1 && entiyMoveCount == 0) { return; } McpeBatch batch = BatchUtils.CreateBatchPacket(stream.GetBuffer(), 0, (int)stream.Length, CompressionLevel.Optimal, false); batch.AddReferences(players.Length - 1); batch.Encode(); //batch.ValidUntil = now + TimeSpan.FromMilliseconds(50); foreach (var player in players) { MiNetServer.FastThreadPool.QueueUserWorkItem(() => player.SendPackage(batch)); } _lastBroadcast = DateTime.UtcNow; } }
public void SendQueue() { if (_sendQueueNotConcurrent.Count == 0) { return; } if (!Monitor.TryEnter(_syncHack)) { return; } try { using (MemoryStream memStream = new MemoryStream()) { Queue <Packet> queue = _sendQueueNotConcurrent; int messageCount = 0; int lenght = queue.Count; for (int i = 0; i < lenght; i++) { Packet packet = null; lock (_queueSync) { if (queue.Count == 0) { break; } try { packet = queue.Dequeue(); } catch (Exception e) { } } if (packet == null) { continue; } if (State == ConnectionState.Unconnected) { packet.PutPool(); continue; } if (lenght == 1) { Server.SendPacket(this, packet); } else if (packet is McpeWrapper) { SendBuffered(messageCount, memStream); messageCount = 0; Server.SendPacket(this, packet); // The following is necessary if no throttling is done on chunk sending, // but having it creates a lot of packet lag when using SpawnLevel. You can see it // as players standing still, but having running particles. // //Thread.Sleep(1); // Really important to slow down speed a bit } else if (packet.NoBatch) { SendBuffered(messageCount, memStream); messageCount = 0; Server.SendPacket(this, packet); } else { if (messageCount == 0) { memStream.Position = 0; memStream.SetLength(0); } byte[] bytes = packet.Encode(); if (bytes != null) { messageCount++; BatchUtils.WriteLength(memStream, bytes.Length); //memStream.Write(BitConverter.GetBytes(Endian.SwapInt32(bytes.Length)), 0, 4); memStream.Write(bytes, 0, bytes.Length); } packet.PutPool(); } } if (State == ConnectionState.Unconnected) { return; } SendBuffered(messageCount, memStream); } } finally { Monitor.Exit(_syncHack); } }