/// <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); }
/// <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); } }
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)); }
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); }
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); }
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); }