public void SendPackage <TOutputStream>() where TOutputStream : struct, NetworkCompression.IOutputStream { // We don't start sending updates before we have received at // least one content package from the server var rawOutputStream = new BitOutputStream(m_PackageBuffer); if (inSequence == 0 || !CanSendPackage(ref rawOutputStream)) { return; } // Only if there is anything to send // TODO (petera) should we send empty packages at a low frequency? if (sendClientConfig == false && commandSequence > 0 && commandSequence <= lastSentCommandSeq && eventsOut.Count == 0) { return; } ClientPackageInfo info; BeginSendPackage(ref rawOutputStream, out info); int endOfHeaderPos = rawOutputStream.Align(); var output = default(TOutputStream); // new TOutputStream(); due to bug new generate garbage here output.Initialize(NetworkCompressionModel.DefaultModel, m_PackageBuffer, endOfHeaderPos, null); if (sendClientConfig) { WriteClientConfig(ref output); } if (commandSequence > 0) { lastSentCommandSeq = commandSequence; WriteCommands(info, ref output); } WriteEvents(info, ref output); int compressedSize = output.Flush(); rawOutputStream.SkipBytes(compressedSize); CompleteSendPackage(info, ref rawOutputStream); }
public void BitStream_Align() { var random = new Random(1293); var numbers = new int[1024]; var buffer = new byte[1024 * 64]; for (int runs = 0; runs < 1000; ++runs) { for (int i = 0; i < 1024; ++i) { numbers[i] = random.Next(1, 33); } var output = new BitOutputStream(buffer); for (int i = 0; i < 1024; ++i) { output.WriteBits((uint)numbers[i], numbers[i]); if (i % 3 == 0) { output.Align(); } } var input = new BitInputStream(buffer); for (int i = 0; i < 1024; ++i) { var value = input.ReadBits(numbers[i]); Assert.AreEqual((uint)numbers[i], value); if (i % 3 == 0) { input.Align(); } } } }
public void SendPackage() { var rawOutputStream = new BitOutputStream(m_PackageBuffer); // Distribute clients evenly according to their with snapshotInterval > 1 // TODO: This kind of assumes same update interval by all .... if ((_server.m_ServerSequence + ConnectionId) % snapshotInterval != 0) { return; } // Respect max bps rate cap if (Game.frameTime < nextOutPackageTime) { return; } ServerPackageInfo packageInfo; BeginSendPackage(ref rawOutputStream, out packageInfo); int endOfHeaderPos = rawOutputStream.Align(); var output = new RawOutputStream();// new TOutputStream(); Due to bug new generates garbage here output.Initialize(m_PackageBuffer, endOfHeaderPos); packageInfo.serverSequence = _server.m_ServerSequence; packageInfo.serverTime = _server.serverTime; // Server time (could be ticks or could be ms) // The ifs below are in essence the 'connection handshake' logic. if (!clientInfoAcked) { // Keep sending client info until it is acked WriteClientInfo(ref output); } else if (!mapAcked) { if (_server.m_MapInfo.serverInitSequence > 0) { // Keep sending map info until it is acked WriteMapInfo(ref output); } } else { // Send snapshot, buf only // if client has declared itself ready // if we have not already sent for this tick (because we need to be able to map a snapshot // sequence to a package sequence we cannot send the same snapshot multiple times). if (mapReady && _server.m_ServerSequence > snapshotServerLastWritten) { WriteSnapshot(ref output); } } int compressedSize = output.Flush(); rawOutputStream.SkipBytes(compressedSize); var messageSize = CompleteSendPackage(packageInfo, ref rawOutputStream); // Decide when next package can go out if (maxBPS > 0) { double timeLimitBPS = messageSize / maxBPS; if (timeLimitBPS > (float)snapshotInterval / Game.serverTickRate.FloatValue) { GameDebug.Log("SERVER: Choked by BPS sending " + messageSize); nextOutPackageTime = Game.frameTime + timeLimitBPS; } } CompleteSendPackage(packageInfo, ref rawOutputStream); }