private void SendQueue() { if (!Monitor.TryEnter(_syncHack)) { return; } try { using (MemoryStream memStream = MiNetServer.MemoryStreamManager.GetStream()) { var now = DateTime.UtcNow; 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 (package.ValidUntil != null && now > package.ValidUntil.Value) { package.PutPool(); continue; } if (lenght == 1) { Server.SendPackage(this, package); } else if (package is McpeBatch) { 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 (!IsSpawned) //{ // SendBuffered(messageCount); // 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.WriteLenght(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.WriteLenght(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.WriteLenght(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.WriteLenght(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; } }