Exemple #1
0
        // helper function to copy a batch to writer and return it to pool
        static void CopyAndReturn(NetworkWriterPooled batch, NetworkWriter writer)
        {
            // make sure the writer is fresh to avoid uncertain situations
            if (writer.Position != 0)
            {
                throw new ArgumentException($"GetBatch needs a fresh writer!");
            }

            // copy to the target writer
            ArraySegment <byte> segment = batch.ToArraySegment();

            writer.WriteBytes(segment.Array, segment.Offset, segment.Count);

            // return batch to pool for reuse
            NetworkWriterPool.Return(batch);
        }
        internal override void Update()
        {
            base.Update();

            // should we still process a connected event?
            if (connectedEventPending)
            {
                connectedEventPending = false;
                NetworkClient.OnConnectedEvent?.Invoke();
            }

            // process internal messages so they are applied at the correct time
            while (queue.Count > 0)
            {
                // call receive on queued writer's content, return to pool
                NetworkWriterPooled writer  = queue.Dequeue();
                ArraySegment <byte> message = writer.ToArraySegment();

                // OnTransportData assumes a proper batch with timestamp etc.
                // let's make a proper batch and pass it to OnTransportData.
                Batcher batcher = GetBatchForChannelId(Channels.Reliable);
                batcher.AddMessage(message, NetworkTime.localTime);

                using (NetworkWriterPooled batchWriter = NetworkWriterPool.Get())
                {
                    // make a batch with our local time (double precision)
                    if (batcher.GetBatch(batchWriter))
                    {
                        NetworkClient.OnTransportData(batchWriter.ToArraySegment(), Channels.Reliable);
                    }
                }

                NetworkWriterPool.Return(writer);
            }

            // should we still process a disconnected event?
            if (disconnectedEventPending)
            {
                disconnectedEventPending = false;
                NetworkClient.OnDisconnectedEvent?.Invoke();
            }
        }
Exemple #3
0
        // batch as many messages as possible into writer
        // returns true if any batch was made.
        public bool MakeNextBatch(NetworkWriter writer, double timeStamp)
        {
            // if we have no messages then there's nothing to do
            if (messages.Count == 0)
            {
                return(false);
            }

            // make sure the writer is fresh to avoid uncertain situations
            if (writer.Position != 0)
            {
                throw new ArgumentException($"MakeNextBatch needs a fresh writer!");
            }

            // write timestamp first
            // -> double precision for accuracy over long periods of time
            writer.WriteDouble(timeStamp);

            // do start no matter what
            do
            {
                // add next message no matter what. even if > threshold.
                // (we do allow > threshold sized messages as single batch)
                NetworkWriterPooled message = messages.Dequeue();
                ArraySegment <byte> segment = message.ToArraySegment();
                writer.WriteBytes(segment.Array, segment.Offset, segment.Count);

                // return the writer to pool
                NetworkWriterPool.Return(message);
            }
            // keep going as long as we have more messages,
            // AND the next one would fit into threshold.
            while (messages.Count > 0 &&
                   writer.Position + messages.Peek().Position <= threshold);

            // we had messages, so a batch was made
            return(true);
        }
Exemple #4
0
        // get next message, unpacked from batch (if any)
        // timestamp is the REMOTE time when the batch was created remotely.
        public bool GetNextMessage(out NetworkReader message, out double remoteTimeStamp)
        {
            // getting messages would be easy via
            //   <<size, message, size, message, ...>>
            // but to save A LOT of bandwidth, we use
            //   <<message, message, ...>
            // in other words, we don't know where the current message ends
            //
            // BUT: it doesn't matter!
            // -> we simply return the reader
            //    * if we have one yet
            //    * and if there's more to read
            // -> the caller can then read one message from it
            // -> when the end is reached, we retire the batch!
            //
            // for example:
            //   while (GetNextMessage(out message))
            //       ProcessMessage(message);
            //
            message = null;

            // do nothing if we don't have any batches.
            // otherwise the below queue.Dequeue() would throw an
            // InvalidOperationException if operating on empty queue.
            if (batches.Count == 0)
            {
                remoteTimeStamp = 0;
                return(false);
            }

            // was our reader pointed to anything yet?
            if (reader.Length == 0)
            {
                remoteTimeStamp = 0;
                return(false);
            }

            // no more data to read?
            if (reader.Remaining == 0)
            {
                // retire the batch
                NetworkWriterPooled writer = batches.Dequeue();
                NetworkWriterPool.Return(writer);

                // do we have another batch?
                if (batches.Count > 0)
                {
                    // point reader to the next batch.
                    // we'll return the reader below.
                    NetworkWriterPooled next = batches.Peek();
                    StartReadingBatch(next);
                }
                // otherwise there's nothing more to read
                else
                {
                    remoteTimeStamp = 0;
                    return(false);
                }
            }

            // use the current batch's remote timestamp
            // AFTER potentially moving to the next batch ABOVE!
            remoteTimeStamp = readerRemoteTimeStamp;

            // if we got here, then we have more data to read.
            message = reader;
            return(true);
        }
Exemple #5
0
 public void Dispose() => NetworkWriterPool.Return(this);