Exemple #1
0
        /// <summary>
        ///     Packs all elements of an enumerable up to a given size.
        ///     Max MAX_LIST_COUNT elements, by default 255.
        /// </summary>
        public byte PackToSize <T>(
            int maxTotalBytes,
            int maxIndividualBytes,
            IEnumerable <T> elements,
            Action <T, RailBitBuffer> encode,
            Action <T> packed = null)
        {
            const int SIZE_BITS = 8;

            maxTotalBytes -= 1; // Sentinel bit can blow this up
            byte count = 0;

            // Reserve: [Count]
            int countWritePos = writePos;

            Write(SIZE_BITS, 0);

            // Write: [Elements]
            foreach (T val in elements)
            {
                if (count == MAX_LIST_COUNT)
                {
                    break;
                }
                int rollback      = writePos;
                int startByteSize = ByteSize;

                encode.Invoke(val, this);

                int endByteSize   = ByteSize;
                int writeByteSize = endByteSize - startByteSize;
                if (writeByteSize > maxIndividualBytes)
                {
                    writePos = rollback;
                    RailDebug.LogWarning("Skipping " + val + " (" + writeByteSize + "B)");
                }
                else if (endByteSize > maxTotalBytes)
                {
                    writePos = rollback;
                    break;
                }
                else
                {
                    packed?.Invoke(val);
                    count++;
                }
            }

            // Deferred Write: [Count]
            Insert(countWritePos, SIZE_BITS, count);
            return(count);
        }
Exemple #2
0
        /// <summary>
        ///     Selects outgoing events to send.
        /// </summary>
        private IEnumerable <RailEvent> FilterOutgoingEvents()
        {
            // The receiving client can only store a limited size sequence history
            // of events in its received buffer, and will skip any events older than
            // its latest received minus that history length, including reliable
            // events. In order to make sure we don't force the client to skip an
            // event with attempts remaining, we will throttle the outgoing events
            // if we've been sending them too fast. For example, if we have a live
            // event with ID 3 pending, and a maximum history length of 64 (see
            // RailConfig.HISTORY_CHUNKS) then the highest ID we can send would be
            // ID 67. Were we to send an event with ID 68, then the client may ignore
            // ID 3 when it comes in for being too old, even though it's still live.
            //
            // In practice this shouldn't be a problem unless we're sending way
            // more events than is reasonable(/possible) in a single packet, or
            // something is wrong with reliable event acking. You can always increase
            // the number of history chunks if this becomes an issue.

            SequenceId firstId = SequenceId.Invalid;

            foreach (RailEvent evnt in outgoingEvents)
            {
                // Ignore dead events, they'll be cleaned up eventually
                if (evnt.Attempts <= 0)
                {
                    continue;
                }

                // Don't send an event if it's out of scope for this peer
                if (Scope != null && Scope.Includes(evnt) == false)
                {
                    // Skipping due to out of scope counts as an attempt
                    evnt.RegisterSkip();
                    continue;
                }

                if (firstId.IsValid == false)
                {
                    firstId = evnt.EventId;
                }
                RailDebug.Assert(firstId <= evnt.EventId);

                if (eventHistory.AreInRange(firstId, evnt.EventId) == false)
                {
                    RailDebug.LogWarning("Throttling events due to lack of ack");
                    break;
                }

                yield return(evnt);
            }
        }
Exemple #3
0
        public static Tick Subtract(Tick a, uint b, bool warnClamp = false)
        {
            long result = a.tickValue - (int)b;

            if (result < 1)
            {
                if (warnClamp)
                {
                    RailDebug.LogWarning("Clamping tick subtraction");
                }
                result = 1;
            }

            return(new Tick((uint)result));
        }
Exemple #4
0
 public uint Pack(int value)
 {
     if ((value < this.minValue) || (value > this.maxValue))
     {
         RailDebug.LogWarning(
             "Clamping value for send! " +
             value +
             " vs. [" +
             this.minValue +
             "," +
             this.maxValue +
             "]");
     }
     return((uint)(value - this.minValue) & this.mask);
 }
Exemple #5
0
        public ulong Pack(long value)
        {
            if (value < minValue || value > maxValue)
            {
                RailDebug.LogWarning(
                    "Clamping value for send! " +
                    value +
                    " vs. [" +
                    minValue +
                    "," +
                    maxValue +
                    "]");
            }

            return((ulong)(value - minValue) & mask);
        }
        public uint Pack(float value)
        {
            float newValue = RailUtil.Clamp(value, this.minValue, this.maxValue);

            if (newValue != value)
            {
                RailDebug.LogWarning(
                    "Clamping value for send! " +
                    value +
                    " vs. [" +
                    this.minValue +
                    "," +
                    this.maxValue +
                    "]");
            }
            float adjusted = (value - this.minValue) * this.invPrecision;

            return((uint)(adjusted + 0.5f) & this.mask);
        }
Exemple #7
0
        private static byte ToASCII(char character)
        {
            byte value;

            try
            {
                value = Convert.ToByte(character);
            }
            catch (OverflowException)
            {
                RailDebug.LogWarning("Cannot convert to simple ASCII: " + character);
                return(0);
            }

            if (value > 127)
            {
                RailDebug.LogWarning("Cannot convert to simple ASCII: " + character);
                return(0);
            }

            return(value);
        }